<p>For both Craft 2 and 3, there are Facated Navigation plugins that handle this for you. </p>

<p><a href="https://plugins.craftcms.com/faceted-navigation" rel="nofollow noreferrer">For Craft 3</a>
<a href="https://github.com/iainurquhart/FacetedNav_CraftPlugin" rel="nofollow noreferrer">For Craft 2</a></p>

CC BY-SA 4.0
2019-10-14T22:52:59.957Z
2019-10-14T22:52:59.957Z
Chad Crowell
<p>First, I would use something like <code>training</code> in your query string. It's a little more readable and you aren't searching for the words <code>lunge</code> and <code>dumbbell</code> <em>anywhere</em> in those entries, just entries related to those category slugs.</p>

<pre><code>{# First you would find any training categories in the URL query string. #}
{% set trainingQuery = craft.request.getParam('training') %}

{# Then find categories that match the slugs in your query string. #}
{% set trainingCategories = craft.categories.group('trainingCategoryGroup').slug(trainingQuery) %}

{# setup your search parameters #}
{% set searchParams = {
  relatedTo:  trainingCategories,
  section: 'exercisesDb'
} %}

{# Find your entries #}
{% set entries = craft.entries(searchParams).order('score') %}
</code></pre>

<p>Your search form just needs to have the checkbox's input name as <code>training[]</code>. If it's on the same page, test to see if the category slug is in the <code>trainingQuery</code> array so it can be marked as <code>checked</code> or not.
Create this by finding all the categories in the <code>trainingCategoryGroup</code> group.</p>

<pre><code>&lt;form action="http://www.website.com/training/exercise-list"&gt;  

  {% for category in craft.categories.group('trainingCategoryGroup') %}
    &lt;label&gt;&lt;input type="checkbox" name="training[]" value="{{ category.slug }}" {{ category.slug in trainingQuery ? 'checked'}}&gt;{{ category.title }}&lt;/label&gt;&lt;br&gt;
  {% endfor %}

  &lt;button type="submit"&gt;Search&lt;/button&gt;  
&lt;/form&gt;
</code></pre>

<p>Then output your list of entries. This is a simple example.</p>

<pre><code>{% if entries | length %}
  &lt;ol&gt;
    {% for entry in entries %}
      &lt;li&gt;
        &lt;a href="{{ entry.url }}"&gt;{{ entry.title }}&lt;/a&gt;&lt;br /&gt;
      &lt;/li&gt;
    {% endfor %}
  &lt;/ol&gt;
{% else %}
  &lt;p&gt;No results&lt;/p&gt;
{% endif %}
</code></pre>

<p>If the query string is blank, this will show all of your entries. If you want to restrict that, you can wrap the previous code block in this...</p>

<pre><code>{% if trainingQuery %}
  ... (entries) ...
{% endif %}
</code></pre>

<p>This is an <strong>inclusive</strong> search that will match entries in ANY selected categories. If you want an <strong>exclusive</strong> search instead (category AND category), you have to do it a little differently.</p>

<pre><code>{# Get search parameters from the URL query string #}
{% set trainingQuery = craft.request.getParam('training') %}

{# Start an array of search parameters (relationParam) with 'and' to match ALL categories #}
{% set relationParam = ['and'] %}

{# Find categories that match the slugs in your query string... #}
{% for querySlug in trainingQuery %}
  {% set trainingCategory = craft.categories.group('trainingCategoryGroup').slug(querySlug) %}

  {# And merge them into the relationParam array. #}
  {% set relationParam = relationParam|merge([{ targetElement: trainingCategory }]) %}
{% endfor %}

{# Avoid passing an array with `['and']` only #}
{% if relationParam|length &lt; 2 %}
  {% set relationParam = '' %}
{% endif %}

{% set searchParams = {
  relatedTo:  relationParam,
  section: 'exercisesDb'
} %}
</code></pre>

CC BY-SA 3.0
2015-04-08T14:37:38.217Z
Thank you Alex!  I wasn't able to get the checkbox working so I manually typed in the query into my browser to test so maybe I have the query string incorrect when adding parameters. When I use the query string `http://www.website.com/training/exercise-list?training=lunge&training=dumbbell` it shows me all entries that contain either "lunge" or "dumbbell" categories.  I'd like it to first filter by "lunge" which outputs say 3 entries, then filter those 3 entries by the second query "dumbbell" which would bring it to show only 1 entry that is categorized as both "lunge" and "dumbell".
Lori
CC BY-SA 3.0
2015-04-09T02:10:53.737Z
Hmm. You may need to use `name="training"` on your checkboxes then instead of `name="training[]"`. I'll add and example of doing a combined search (cat AND cat).
Alex Roper
CC BY-SA 3.0
2015-04-11T01:29:22.407Z
Alex, I can't seem to get the new "cat AND cat" code to work. I can't get all my code in the this comments field because it's too many characters.  Here are your variables and mine.
`toolTypeQuery = trainingQuery` • 
`relationParam = relationParam ` • 
`querySlug = querySlug ` • 
`toolType = trainingCategories` • 
`collaborationToolTypes = trainingCategoryGroup` • 
`collaborationTools = exercisesDb` • My URL looks like this: `http://www.website.com/training/exercise-list?training=lunge&training=dumbbell` (I'm manually typing in URL so maybe my string is incorrect?)
Lori
CC BY-SA 3.0
2015-04-11T09:01:19.413Z
Sorry, my new example had the wrong variable names specific to my projects. I updated them with your variables names. Try it now. 

If you still have trouble, you can edit your original question and add your code, or send the complete code with a Github Gist or Pastebin snippet.
Alex Roper
CC BY-SA 3.0
2015-04-11T14:08:35.373Z
Hi Alex.  Darn, still can't get the code to work.  I pasted my trimmed down code into Pastebin as you suggested.  In addition to your code I also included the entries loop in case that's incorrect. http://pastebin.com/raw.php?i=vxxszY62
Lori
CC BY-SA 3.0
2015-04-12T10:52:43.740Z
Try using `{% set entries = craft.entries(searchParams).order('score') %}` first to make sure that works. It looks like want to sort these entries by 2 variables, `level2` and `title`. To do that you'll need to add the sort direction after each like `.order('level2 desc, title desc')`. See this answer: http://craftcms.stackexchange.com/questions/8744/how-do-i-sort-entries-by-two-variables/8748#8748
Alex Roper
CC BY-SA 3.0
2015-04-12T20:55:07.837Z
Nope, changing (searchParams).order to 'score' didn't make a difference.  I am successfully using the two .order filters with your original code which is filtering by one query as well as your second version of the code which is adding two filters together.  I can't get the third version to work though.  Sorry.
Lori
CC BY-SA 3.0
2015-04-13T09:00:00.287Z
I think the problem must be in your URL. I think you need brackets after "training" in the query string: `?training[]=lunge&training[]=dumbbell` or possibly the UTF-8 encoding: `?training%5B%5D=lunge&training%5B%5D=dumbbell`. You can try to use the `{{ dump() }}` tag to view the raw contents of your variables and arrays. When you use `<pre>{{ dump(trainingQuery) }}</pre>`, it should return an array, not a string. Like this: http://pastebin.com/ZxSzNhWG
Alex Roper
CC BY-SA 3.0
2015-04-13T09:41:58.523Z
You figured it out!  It was the URL string.  It needs to have the brackets after the "trainining".  So `?training[]=lunge&training[]=dumbbell`.  Thank you so much for your continued help with this Alex.  I sincerely appreciate it!
Lori
CC BY-SA 3.0
2015-07-17T14:41:52.503Z
This worked well for me -- I used the first snippet, but replaced the getParam in the first line with the value from a cookie. Thanks for the help.
Neal Magee
CC BY-SA 3.0
2015-11-10T16:17:40.823Z
@alexroper Thanks for explaining all of this! Have been trying to solve the AND query for a while. Had no idea about using the brackets in the query string.
jthomas
CC BY-SA 3.0
2016-02-09T16:30:17.607Z
@alexroper thank you for this it is extremely helpful. One question if you don't mind, if I want to work with multiple category groups using the exclusive version of your code how could I make that work? I have created a pastebin where I add multiple targetElements http://pastebin.com/K5NxBwp0 is that the correct approach as this still seems to be working inclusive.
Gareth
CC BY-SA 3.0
2016-02-21T03:10:09.987Z
@Gareth [Have you tried something like in this answer?](http://craftcms.stackexchange.com/a/6942/273) If that doesn't work, it might be easier to answer if you create a new question.
Alex Roper
CC BY-SA 3.0
2016-02-22T14:20:30.217Z
@alexroper thank you I'll take a look at that, I did re-post but didn't get any answers http://craftcms.stackexchange.com/questions/13656/how-to-filter-entries-in-multiple-category-groups-by-clicking-multiple-categorie
Gareth
CC BY-SA 3.0
2015-04-08T07:18:44.190Z
2015-04-11T08:56:44.953Z
2015-04-11T08:56:44.953Z
Alex Roper
<p>I would like to be able to filter my entries list by multiple categories on the front end. For example, if I first click a category button "lunge" then the results would show entries which are categorized as "lunge".  If I click a second category button labeled "dumbbell" then the results would be filtered more and show only entries that are categorized as both "lunge" and "dumbbell".</p>

<p>I found some similar threads but haven't been able to get the suggestions to work for me.  I believe I need to pass the categories into a URL query string like this:</p>

<p><code>www.website.com/training/exercise-list?q=lunge,dumbbell</code></p>

<p>where <code>q</code> is my search query parameter and <code>lunge</code> and <code>dumbbell</code> are the categories that were clicked.</p>

<ul>
<li>Section is called <code>exercisesDb</code></li>
<li>Category Group is called<code>trainingCategoryGroup</code></li>
<li>Category Field in the section is called
<code>trainingCategory</code></li>
</ul>

<p>Thanks so much!</p>

<categories><search><filter><category>
How to filter entries by clicking multiple categories on front end
# How to filter entries by clicking multiple categories on front end

(Asked by: username_0 on 2015-04-08)

I would like to be able to filter my entries list by multiple categories on the front end. For example, if I first click a category button "lunge" then the results would show entries which are categorized as "lunge". If I click a second category button labeled "dumbbell" then the results would be filtered more and show only entries that are categorized as both "lunge" and "dumbbell".

I found some similar threads but haven't been able to get the suggestions to work for me. I believe I need to pass the categories into a URL query string like this:

`www.website.com/training/exercise-list?q=lunge,dumbbell`

where `q` is my search query parameter and `lunge` and `dumbbell` are the categories that were clicked.

* Section is called `exercisesDb`
* Category Group is called`trainingCategoryGroup`
* Category Field in the section is called
  `trainingCategory`

Thanks so much!

**Tags:** categories, search, filter, category


---

## 2 answers

### Answer by username_2 on 2015-04-08. Score: 11 | Accepted answer

First, I would use something like training in your query string. It's a little more readable and you aren't searching for the words lunge and dumbbell anywhere in those entries, just entries related to those category slugs.
{# First you would find any training categories in the URL query string. #}
{% set trainingQuery = craft.request.getParam('training') %}

{# Then find categories that match the slugs in your query string. #}
{% set trainingCategories = craft.categories.group('trainingCategoryGroup').slug(trainingQuery) %}

{# setup your search parameters #}
{% set searchParams = {
  relatedTo:  trainingCategories,
  section: 'exercisesDb'
} %}

{# Find your entries #}
{% set entries = craft.entries(searchParams).order('score') %}

Your search form just needs to have the checkbox's input name as training[]. If it's on the same page, test to see if the category slug is in the trainingQuery array so it can be marked as checked or not.
Create this by finding all the categories in the trainingCategoryGroup group.
  

  {% for category in craft.categories.group('trainingCategoryGroup') %}
    {{ category.title }}
  {% endfor %}

  Search  


Then output your list of entries. This is a simple example.
{% if entries | length %}
  
    {% for entry in entries %}
      
        {{ entry.title }}
      
    {% endfor %}
  
{% else %}
  No results
{% endif %}

If the query string is blank, this will show all of your entries. If you want to restrict that, you can wrap the previous code block in this...
{% if trainingQuery %}
  ... (entries) ...
{% endif %}

This is an inclusive search that will match entries in ANY selected categories. If you want an exclusive search instead (category AND category), you have to do it a little differently.
{# Get search parameters from the URL query string #}
{% set trainingQuery = craft.request.getParam('training') %}

{# Start an array of search parameters (relationParam) with 'and' to match ALL categories #}
{% set relationParam = ['and'] %}

{# Find categories that match the slugs in your query string... #}
{% for querySlug in trainingQuery %}
  {% set trainingCategory = craft.categories.group('trainingCategoryGroup').slug(querySlug) %}

  {# And merge them into the relationParam array. #}
  {% set relationParam = relationParam|merge([{ targetElement: trainingCategory }]) %}
{% endfor %}

{# Avoid passing an array with `['and']` only #}
{% if relationParam|length < 2 %}
  {% set relationParam = '' %}
{% endif %}

{% set searchParams = {
  relatedTo:  relationParam,
  section: 'exercisesDb'
} %}

> **Comments:**
> **username_0**: Thank you Alex!  I wasn't able to get the checkbox working so I manually typed in the query into my browser to test so maybe I have the query string incorrect when adding parameters. When I use the query string `http://www.website.com/training/exercise-list?training=lunge&training=dumbbell` it shows me all entries that contain either "lunge" or "dumbbell" categories.  I'd like it to first filter by "lunge" which outputs say 3 entries, then filter those 3 entries by the second query "dumbbell" which would bring it to show only 1 entry that is categorized as both "lunge" and "dumbell".  
> **username_2**: Hmm. You may need to use `name="training"` on your checkboxes then instead of `name="training[]"`. I'll add and example of doing a combined search (cat AND cat).  
> **username_0**: Alex, I can't seem to get the new "cat AND cat" code to work. I can't get all my code in the this comments field because it's too many characters.  Here are your variables and mine. `toolTypeQuery = trainingQuery` •  `relationParam = relationParam ` •  `querySlug = querySlug ` •  `toolType = trainingCategories` •  `collaborationToolTypes = trainingCategoryGroup` •  `collaborationTools = exercisesDb` • My URL looks like this: `http://www.website.com/training/exercise-list?training=lunge&training=dumbbell` (I'm manually typing in URL so maybe my string is incorrect?)  
> **username_2**: Sorry, my new example had the wrong variable names specific to my projects. I updated them with your variables names. Try it now.   If you still have trouble, you can edit your original question and add your code, or send the complete code with a Github Gist or Pastebin snippet.  
> **username_0**: Hi Alex.  Darn, still can't get the code to work.  I pasted my trimmed down code into Pastebin as you suggested.  In addition to your code I also included the entries loop in case that's incorrect. http://pastebin.com/raw.php?i=vxxszY62  
> **username_2**: Try using `{% set entries = craft.entries(searchParams).order('score') %}` first to make sure that works. It looks like want to sort these entries by 2 variables, `level2` and `title`. To do that you'll need to add the sort direction after each like `.order('level2 desc, title desc')`. See this answer: http://craftcms.stackexchange.com/questions/8744/how-do-i-sort-entries-by-two-variables/8748#8748  
> **username_0**: Nope, changing (searchParams).order to 'score' didn't make a difference.  I am successfully using the two .order filters with your original code which is filtering by one query as well as your second version of the code which is adding two filters together.  I can't get the third version to work though.  Sorry.  
> **username_2**: I think the problem must be in your URL. I think you need brackets after "training" in the query string: `?training[]=lunge&training[]=dumbbell` or possibly the UTF-8 encoding: `?training%5B%5D=lunge&training%5B%5D=dumbbell`. You can try to use the `{{ dump() }}` tag to view the raw contents of your variables and arrays. When you use `<pre>{{ dump(trainingQuery) }}</pre>`, it should return an array, not a string. Like this: http://pastebin.com/ZxSzNhWG  
> **username_0**: You figured it out!  It was the URL string.  It needs to have the brackets after the "trainining".  So `?training[]=lunge&training[]=dumbbell`.  Thank you so much for your continued help with this Alex.  I sincerely appreciate it!  
> **username_3**: This worked well for me -- I used the first snippet, but replaced the getParam in the first line with the value from a cookie. Thanks for the help.  
> **username_4**: @alexroper Thanks for explaining all of this! Have been trying to solve the AND query for a while. Had no idea about using the brackets in the query string.  
> **username_5**: @alexroper thank you for this it is extremely helpful. One question if you don't mind, if I want to work with multiple category groups using the exclusive version of your code how could I make that work? I have created a pastebin where I add multiple targetElements http://pastebin.com/K5NxBwp0 is that the correct approach as this still seems to be working inclusive.  
> **username_2**: @username_5 [Have you tried something like in this answer?](http://craftcms.stackexchange.com/a/6942/273) If that doesn't work, it might be easier to answer if you create a new question.  
> **username_5**: @alexroper thank you I'll take a look at that, I did re-post but didn't get any answers http://craftcms.stackexchange.com/questions/13656/how-to-filter-entries-in-multiple-category-groups-by-clicking-multiple-categorie  

---

### Answer by username_1 on 2019-10-14. Score: 1

For both Craft 2 and 3, there are Facated Navigation plugins that handle this for you.

[For Craft 3](https://plugins.craftcms.com/faceted-navigation)
[For Craft 2](https://github.com/iainurquhart/FacetedNav_CraftPlugin)


---

