2

I have a page where by default it lists all of the entries inside the section 'work'. I'd like to have a secondary menu where I can filter these entries by the field 'projectCategories'.

        {% for entry in craft.entries.section('work').find() %}

            <li class="wp-project">

                {% for asset in entry.mainProjectImage %}
                    <a href="{{ entry.url }}" class="project-link">
                         <img src="{{ asset.getUrl('workPageImage')}}" alt="{{ asset.title }}" />
                    </a>
                {% endfor %}

                <p class="project-title">{{ entry.title }}</p>

                <p class="project-categories">
                    {% for option in entry.projectCategories %}

                        {% if loop.last %}
                            {{ option }}

                        {% else %}
                            {{ option }} +

                        {% endif %}

                    {% endfor %}
                </p>
            </li>

        {% endfor %}

My current solution is a secondary menu above the entries that links to a url where it filters the entry for just for that project category with:

{% for entry in craft.entries.section('work').search('projectCategories:Packaging') %}

This works but isn't DRY and unfortunately because of AJAX the secondary menu fades out and back in again when you change the URL.

Is there a way to filter entries by a field without changing the url? Or alternatively is there a way of making the secondary menu not reload with AJAX when on a url that begins with 'work'?

4
  • When I visit the work url, are you showing me all of the work by default? For example, if I choose a filter, is the system hiding all irrelevant entries that don't belong to the chosen filter? Or, are you needing to request new entires for any given filter?
    – Damon
    Nov 24, 2015 at 19:32
  • This doesn't really sound like a Craft question? If you already have all the entries in the same page, and just want to filter the contents without doing a new server request, you should just implement the filtering with Javascript? You could either use a full-blown library like Isotope (isotope.metafizzy.co), or a few lines of jquery code. Nov 24, 2015 at 22:50
  • @Damon Yes by default the work page will show all of the entries in work. So I don't think I'd need to request any new entries. Nov 25, 2015 at 0:57
  • @AndréElvan I just thought maybe there was simple way of filtering entries in craft so that's why I asked here. I think that Isotope library might be what I'm looking for, thanks André. Nov 25, 2015 at 1:00

1 Answer 1

1

Ok so if you are showing all of the entries by default, lets say you have 10 entires in your "work" section.

I am assuming that you have a category group(s) that each entry belongs to. From there I would assign the category in a data attribute. This would give you a hook that you could talk to for filtering.

twig

{# Get all entries within the work section #}
{% set entries = craft.entries.section('work').find() %}

{% if entries|length %}
<ul id="myNav">
    {% for entry in entries %}
        <li data-category="{{ entry.category }}><a href={{ entry.url }}">{{ entry.title }}</a></li>
    {% endfor %}
</ul>
{% endif %}

{# data-category="{{ entry.category }}" could be data-category="my-category" #}

Then I would have a drop-down, or a set of links that represented each of my categories.

twig

{# Get all categories within the work category group #}
{% set category = craft.categories.group('work') %}

<select id="workFilter" name="workFilter">
    <option value="">Select Location</option>
    {% for cat in category %}
        <option value="{{ cat.slug }}">{{ cat.title }}</option>
    {% endfor %}
</select>

On the javascript side, you could either listen for a click - and hide whatever nav items did not have the same data-category value.

For example:

html

<a href="javascript:void(0);" data-target="my-category" class="nav-filter">

Use a click event to check the data value, and hide whatever nav elements did not have "my-category" as the data-category attribute.

Or, a drop-down like above.

jquery

$('#workFilter').change(function (event) {
    // get the value of the drop-down. Hide all list items that do not have the same data-category value.
});

You shouldn't need any ajax or anything like that since all of your entries are already on the page. You just need a hook to show/hide them.

Hope this helps!

EDIT

Sure - give fadeOut a look.

If you are using a button/link you can listen for the click event. Then fadeOut the element. That will fade it out, then set the display to none which should remove the empty gaps for you.

Something like this...

jquery

$('nav-element').click(function(event){
    $('all-things-not-matching).fadeOut('fast', function() {
        // Animation complete.
    });

    event.preventDefault();
});

Each element that is now hidden has the css values of:

opacity: 0;
display: none;
3
  • Hi Damon, thanks for your help. I've managed to get this working but now when I click on a category in the menu it hides everything that isn't in that category but unfortunately they leave a large gap where they used to be. I tried using .remove() which eliminates this problem but means that the element is removed from the DOM completely so that element won't appear if you click another menu item. I'm new to jQuery, is there an alternative to .hide() or .remove() that I can use? Nov 26, 2015 at 16:53
  • I just updated my answer - see if that helps you out.
    – Damon
    Nov 27, 2015 at 1:57
  • Awesome! Glad it helped you out.
    – Damon
    Nov 29, 2015 at 1:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.