Created
December 14, 2018 20:17
-
-
Save samhernandez/54f8ab8cbd464d94ad77a2adeeaab6a8 to your computer and use it in GitHub Desktop.
Dependent category filter navs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{# | |
Assuming: | |
- this route is like: `/listing/[primary category slug]/[secondary category slug]` | |
- the secondary category nav should only show what is relevant to the primary category | |
#} | |
{% set slug1 = craft.app.request.segment(2) %} | |
{% set slug2 = craft.app.request.segment(3) %} | |
{% set primaryCat = craft.categories.group('primaryCategory').slug(slug1).one() %} | |
{% set secondaryCat = craft.categories.group('secondaryCategory').slug(slug2).one() %} | |
{# | |
It's probaby a good idea to cache this nav section so these queries | |
don't need to run on every page load. We'll handle the `.active` css | |
class with a `replace()` method on the cached content. | |
#} | |
{% set navs %} | |
{% cache using key slug1 ~ '/' ~ slug2 %} | |
{# | |
Primary category nav | |
- only show categories that have entries | |
- cache so these big queries don't need to happen every request | |
#} | |
{% set allProductIds = craft.entries.section('mySection').ids() %} | |
{% set primaryCatsToShow = craft.categories.group('primaryCategory').relatedTo(allProductIds).all() %} | |
<ul> | |
{% for cat in primaryCatsToShow %} | |
<li class="active-{{ cat.slug }}"><a href="/listing/{{ cat.slug }}/all">{{ cat.title }}</a></li> | |
{% endfor %} | |
</ul> | |
{# | |
Secondary category nav | |
- Only show categories that have entries related to | |
the primary category | |
#} | |
{% set filteredProductIds = craft.entries.section('mySection').relatedTo(primaryCat).ids() %} | |
{% set secondaryCatsToShow = craft.categories.group('secondaryCategory').relatedTo(filteredProductIds).all() %} | |
<ul> | |
{% for cat in secondaryCatsToShow %} | |
<li class="active-{{ cat.slug }}"><a href="/listing/{{ slug1 }}/{{ cat.slug }}">{{ cat.title }}</a></li> | |
{% endfor %} | |
</ul> | |
{% endcache %} | |
{% endset %} | |
{# | |
Now, on the cached content, we can replace `active-some-slug` with just `active` | |
for the current page slugs. | |
#} | |
{{ navs | replace('active-' ~ slug1, 'active') | replace('active-' ~ slug2, 'active') | raw }} | |
<hr> | |
{# | |
Build a `relatedTo` param (array) | |
- the first value should be 'and' so entries must have cat1 *and* cat2 | |
(default behavior is an entry can match cat1 *or* cat2 - more results) | |
- then we'll pass elements as the remaining array items | |
- we won't assume either category was found | |
Example | |
``` | |
[ | |
'and', | |
{element: primaryCat}, | |
{element: secondaryCat} | |
] | |
``` | |
#} | |
{% set relatedToParam = ['and'] %} | |
{% if primaryCat %} | |
{% set relatedToParam = relatedToParam | merge([{element: primaryCat}]) %} | |
{% endif %} | |
{% if secondaryCat %} | |
{% set relatedToParam = relatedToParam | merge([{element: secondaryCat}]) %} | |
{% endif %} | |
{# | |
We'll use a criteria object for simplicity. | |
It could end up like this: | |
``` | |
{ | |
section: 'mySection', | |
relatedTo: [ | |
'and', | |
{element: primaryCat}, | |
{element: secondaryCat} | |
] | |
} | |
``` | |
#} | |
{% set criteria = {section: 'mySection'} %} | |
{# Only if we have more than just `['and']` #} | |
{% if relatedToParam | length > 1 %} | |
{% set criteria = criteria | merge({relatedTo: relatedToParam}) %} | |
{% endif %} | |
{# The list #} | |
<ul> | |
{% for entry in craft.entries(criteria).all() %} | |
<li>{{ entry.title }}</li> | |
{% endfor %} | |
</ul> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment