How to filter entries by clicking multiple categories on front end 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 calledtrainingCategoryGroup
Category Field in the section is called
trainingCategory


Thanks so much!
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.

&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;


Then output your list of entries. This is a simple example.

{% 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 %}


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 &lt; 2 %}
  {% set relationParam = '' %}
{% endif %}

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