<p>Before I answer your main question, I'm seeing a couple issues with what you’re currently doing that are worth correcting.</p>

<p>First, this code:</p>

<pre><code>{% set supplierCat = craft.categories.group('supplier').slug(supplier).first %}
{% set productCat = craft.categories.group('product').slug(product).first %}
{% set deliveryCat = craft.categories.group('delivery').slug(delivery).first %}
</code></pre>

<p>should be replaced with:</p>

<pre><code>{% set supplierCat = supplier ? craft.categories.group('supplier').slug(supplier).first %}
{% set productCat = product ? craft.categories.group('product').slug(product).first %}
{% set deliveryCat = delivery ? craft.categories.group('delivery').slug(delivery).first %}
</code></pre>

<p>in case any of the <code>supplier</code>/<code>product</code>/<code>delivery</code> params are blank.</p>

<p>Next, this code:</p>

<pre><code>{% set supplierParam = supplier ? {targetElement: supplierCat} : '' %}
{% set productParam = product ? {targetElement: productCat} : '' %}
{% set deliveryParam = delivery ? {targetElement: deliveryCat} : '' %}
</code></pre>

<p>should be replaced with:</p>

<pre><code>{% set supplierParam = supplierCat ? {targetElement: supplierCat} %}
{% set productParam = productCat ? {targetElement: productCat} %}
{% set deliveryParam = deliveryCat ? {targetElement: deliveryCat} %}
</code></pre>

<p>That way you will avoid unexpected behavior if a supplier/product/delivery was <em>posted</em>, but it had an invalid slug, and yielded no results. Also, the <code>: ''</code>s at the end are just not really necessary unless your <em>really</em> wanted them to be strings by default (no reason in this case though), as Twig will default the values to <code>null</code>, which is just as good.</p>

<p>Also, you can’t chain multiple <code>relatedTo</code> params together like this:</p>



<pre class="lang-twig prettyprint-override"><code>.relatedTo(productParam).relatedTo(deliveryParam)
</code></pre>

<p>When you do that, the second <code>relatedTo</code> param will just override the 1st one.</p>

<p>Instead you’d need to do something like:</p>

<pre class="lang-twig prettyprint-override"><code>{% set relationParams = [supplierParam, productParam, deliveryParam]|filter %}

{% set entries = craft.entries({
    section: 'suppliers',
    relatedTo: relationParams ? ['and']|merge(relationParams) : null,
    search: query,
    homeGrown: homeGrownParam,
    preparedProduce: preparedProduceParam,
    redTractor: redTractorParam
}) %}
</code></pre>

<p><em>(I’m using the <code>{p1: v1, p2: v2}</code> syntax for setting the criteria params here for clarity, but you can use the <code>p1(v1).p2(v2)</code> chaining syntax instead if you prefer it.)</em></p>

<hr>

<p>With that out of the way…</p>

<p>To support searching for entries that are related to <em>multiple</em> suppliers/products/deliveries at the same time, the first thing you’ll need to do is update your search form. I know you said you want to go with checkboxes, but for simplicity’s sake I’ll demonstrate with multi-select boxes, since that’s closer to your original code and produces the same request param data.</p>

<p>For each of your <code>&lt;select&gt;</code>s, just append a <code>[]</code> to the input name and add the <code>multiple</code> attribute:</p>

<pre class="lang-twig prettyprint-override"><code>&lt;select name="supplier[]" multiple&gt;
...
&lt;select name="product[]" multiple&gt;
...
&lt;select name="delivery[]" multiple&gt;
...
</code></pre>

<p>In your search results template, change <code>.first</code> to <code>.find()</code> when fetching the categories:</p>

<pre class="lang-twig prettyprint-override"><code>{% set supplierCat = supplier ? craft.categories.group('supplier').slug(supplier).find() %}
{% set productCat = product ? craft.categories.group('product').slug(product).find() %}
{% set deliveryCat = delivery ? craft.categories.group('delivery').slug(delivery).find() %}
</code></pre>

<p>And assuming you want this to be an <em>inclusive</em> search (where only results with <em>all</em> of the selected suppliers should be included, etc.), you’ll need to prepend <code>'and'</code> to each of the <code>targetElement</code> arrays:</p>

<pre class="lang-twig prettyprint-override"><code>{% set supplierParam = supplierCat ? {targetElement: ['and']|merge(supplierCat)}l %}
{% set productParam = productCat ? {targetElement: ['and']|merge(productCat)} %}
{% set deliveryParam = deliveryCat ? {targetElement: ['and']|merge(deliveryCat)} %}
</code></pre>

<p>That’s it. The rest can stay the same.</p>

CC BY-SA 3.0
2017-03-03T15:31:20.760Z
There's a letter "l" at the end of this `{% set supplierParam = supplierCat ? {targetElement: supplierCat}l %}`, was that intended?
Jose
CC BY-SA 3.0
2017-03-03T15:34:42.783Z
Works great! I just had to add a `selected` attribute to the first option in the select dropdown block. So the code looks something like this: `<option value="" selected>All Products</option>`
Jose
CC BY-SA 3.0
2017-03-03T16:12:38.447Z
Interestingly, if I don't have the `selected` attribute on the first option of the three select boxes, it doesn't work? Why's that?
Jose
CC BY-SA 3.0
2017-03-03T17:31:43.310Z
@Jose Just [updated the answer](http://craftcms.stackexchange.com/posts/19258/revisions) to address the possibility of `supplier`/`product`/`delivery` params being blank.
Brandon Kelly
CC BY-SA 3.0
2017-03-03T12:43:24.003Z
2017-03-03T17:30:32.170Z
2017-03-03T17:30:32.170Z
Brandon Kelly
<p>Been scratching my head for the past day on how to implement search with multiple categories. </p>

<p>At the moment, I have product categories as a select dropdown which only allows to search in one category at a time. This is passing the value as a parameter. How do I go about searching with multiple categories (checkboxes) at once? Here's what I have so far. </p>

<p>Any ideas?</p>

<p><strong>search.html</strong></p>

<pre><code>&lt;form action="{{ url('food-suppliers/results') }}"&gt;
    &lt;input type="search" name="query" placeholder="What are you looking for?" style="width: 100%;"&gt;

    &lt;select name="supplier"&gt;
      &lt;option value=""&gt;All Markets&lt;/option&gt;
      {% set suppliers = craft.categories.group('suppliers') %}
      {% for supplier in suppliers %}
      &lt;option value="{{ supplier.slug }}"&gt;{{ supplier.title }}&lt;/option&gt;
      {% endfor %}
    &lt;/select&gt;

    &lt;select name="product"&gt;
      &lt;option value=""&gt;All Products&lt;/option&gt;
      {% set products = craft.categories.group('product') %}
      {% for product in products %}
      &lt;option value="{{ product.slug }}"&gt;{{ product.title }}&lt;/option&gt;
      {% endfor %}
    &lt;/select&gt;

    &lt;select name="delivery"&gt;
      &lt;option value=""&gt;All Delivery&lt;/option&gt;
      {% set deliveries = craft.categories.group('delivery') %}
      {% for delivery in deliveries %}
      &lt;option value="{{ delivery.slug }}"&gt;{{ delivery.title }}&lt;/option&gt;
      {% endfor %}
    &lt;/select&gt;

    &lt;div class=""&gt;
      &lt;input type="checkbox" name="homeGrown" value="true"&gt;Home Grown&lt;br/&gt;
      &lt;input type="checkbox" name="preparedProduce" value="true"&gt;Prepared Produce&lt;br/&gt;
      &lt;input type="checkbox" name="redTractor" value="true"&gt;Red Tractor&lt;br/&gt;
    &lt;/div&gt;

    &lt;div class=""&gt;
      &lt;input type="submit" value="Search"&gt;
    &lt;/div&gt;

&lt;/form&gt;
</code></pre>

<p><strong>results.html</strong></p>

<pre><code>{% set query = craft.request.getParam('q') %}
{% set supplier = craft.request.getParam('supplier') %}
{% set product = craft.request.getParam('product') %}
{% set delivery = craft.request.getParam('delivery') %}

{% set homeGrownParam = craft.request.getParam('homeGrown') %}
{% set preparedProduceParam = craft.request.getParam('preparedProduce') %}
{% set redTractorParam = craft.request.getParam('redTractor') %}


{% set supplierCat = craft.categories.group('supplier').slug(supplier).first %}
{% set productCat = craft.categories.group('product').slug(product).first %}
{% set deliveryCat = craft.categories.group('delivery').slug(delivery).first %}


{% set supplierParam = supplier ? {targetElement: supplierCat} : '' %}
{% set productParam = product ? {targetElement: productCat} : '' %}
{% set deliveryParam = delivery ? {targetElement: deliveryCat} : '' %}


{% set entries = craft.entries.section('suppliers').relatedTo(productParam).relatedTo(deliveryParam).search(query).homeGrown(homeGrownParam).preparedProduce(preparedProduceParam).redTractor(redTractorParam) %}
</code></pre>

<search>
Advanced Search with tags and categories
# Advanced Search with tags and categories

(Asked by: username_0 on 2017-03-03)

Been scratching my head for the past day on how to implement search with multiple categories. 
At the moment, I have product categories as a select dropdown which only allows to search in one category at a time. This is passing the value as a parameter. How do I go about searching with multiple categories (checkboxes) at once? Here's what I have so far. 
Any ideas?
search.html

    

    
      All Markets
      {% set suppliers = craft.categories.group('suppliers') %}
      {% for supplier in suppliers %}
      {{ supplier.title }}
      {% endfor %}
    

    
      All Products
      {% set products = craft.categories.group('product') %}
      {% for product in products %}
      {{ product.title }}
      {% endfor %}
    

    
      All Delivery
      {% set deliveries = craft.categories.group('delivery') %}
      {% for delivery in deliveries %}
      {{ delivery.title }}
      {% endfor %}
    

    
      Home Grown
      Prepared Produce
      Red Tractor
    

    
      
    



results.html
{% set query = craft.request.getParam('q') %}
{% set supplier = craft.request.getParam('supplier') %}
{% set product = craft.request.getParam('product') %}
{% set delivery = craft.request.getParam('delivery') %}

{% set homeGrownParam = craft.request.getParam('homeGrown') %}
{% set preparedProduceParam = craft.request.getParam('preparedProduce') %}
{% set redTractorParam = craft.request.getParam('redTractor') %}


{% set supplierCat = craft.categories.group('supplier').slug(supplier).first %}
{% set productCat = craft.categories.group('product').slug(product).first %}
{% set deliveryCat = craft.categories.group('delivery').slug(delivery).first %}


{% set supplierParam = supplier ? {targetElement: supplierCat} : '' %}
{% set productParam = product ? {targetElement: productCat} : '' %}
{% set deliveryParam = delivery ? {targetElement: deliveryCat} : '' %}


{% set entries = craft.entries.section('suppliers').relatedTo(productParam).relatedTo(deliveryParam).search(query).homeGrown(homeGrownParam).preparedProduce(preparedProduceParam).redTractor(redTractorParam) %}

**Tags:** search

---

## 1 answers

### Answer by username_1 on 2017-03-03. Score: 5 | Accepted answer

Before I answer your main question, I'm seeing a couple issues with what you’re currently doing that are worth correcting.
First, this code:
{% set supplierCat = craft.categories.group('supplier').slug(supplier).first %}
{% set productCat = craft.categories.group('product').slug(product).first %}
{% set deliveryCat = craft.categories.group('delivery').slug(delivery).first %}

should be replaced with:
{% set supplierCat = supplier ? craft.categories.group('supplier').slug(supplier).first %}
{% set productCat = product ? craft.categories.group('product').slug(product).first %}
{% set deliveryCat = delivery ? craft.categories.group('delivery').slug(delivery).first %}

in case any of the supplier/product/delivery params are blank.
Next, this code:
{% set supplierParam = supplier ? {targetElement: supplierCat} : '' %}
{% set productParam = product ? {targetElement: productCat} : '' %}
{% set deliveryParam = delivery ? {targetElement: deliveryCat} : '' %}

should be replaced with:
{% set supplierParam = supplierCat ? {targetElement: supplierCat} %}
{% set productParam = productCat ? {targetElement: productCat} %}
{% set deliveryParam = deliveryCat ? {targetElement: deliveryCat} %}

That way you will avoid unexpected behavior if a supplier/product/delivery was posted, but it had an invalid slug, and yielded no results. Also, the : ''s at the end are just not really necessary unless your really wanted them to be strings by default (no reason in this case though), as Twig will default the values to null, which is just as good.
Also, you can’t chain multiple relatedTo params together like this:
.relatedTo(productParam).relatedTo(deliveryParam)

When you do that, the second relatedTo param will just override the 1st one.
Instead you’d need to do something like:
{% set relationParams = [supplierParam, productParam, deliveryParam]|filter %}

{% set entries = craft.entries({
    section: 'suppliers',
    relatedTo: relationParams ? ['and']|merge(relationParams) : null,
    search: query,
    homeGrown: homeGrownParam,
    preparedProduce: preparedProduceParam,
    redTractor: redTractorParam
}) %}

(I’m using the {p1: v1, p2: v2} syntax for setting the criteria params here for clarity, but you can use the p1(v1).p2(v2) chaining syntax instead if you prefer it.)

With that out of the way…
To support searching for entries that are related to multiple suppliers/products/deliveries at the same time, the first thing you’ll need to do is update your search form. I know you said you want to go with checkboxes, but for simplicity’s sake I’ll demonstrate with multi-select boxes, since that’s closer to your original code and produces the same request param data.
For each of your s, just append a [] to the input name and add the multiple attribute:

...

...

...

In your search results template, change .first to .find() when fetching the categories:
{% set supplierCat = supplier ? craft.categories.group('supplier').slug(supplier).find() %}
{% set productCat = product ? craft.categories.group('product').slug(product).find() %}
{% set deliveryCat = delivery ? craft.categories.group('delivery').slug(delivery).find() %}

And assuming you want this to be an inclusive search (where only results with all of the selected suppliers should be included, etc.), you’ll need to prepend 'and' to each of the targetElement arrays:
{% set supplierParam = supplierCat ? {targetElement: ['and']|merge(supplierCat)}l %}
{% set productParam = productCat ? {targetElement: ['and']|merge(productCat)} %}
{% set deliveryParam = deliveryCat ? {targetElement: ['and']|merge(deliveryCat)} %}

That’s it. The rest can stay the same.

> **Comments:**
> **username_0**: There's a letter "l" at the end of this `{% set supplierParam = supplierCat ? {targetElement: supplierCat}l %}`, was that intended?  
> **username_0**: Works great! I just had to add a `selected` attribute to the first option in the select dropdown block. So the code looks something like this: `<option value="" selected>All Products</option>`  
> **username_0**: Interestingly, if I don't have the `selected` attribute on the first option of the three select boxes, it doesn't work? Why's that?  
> **username_1**: @Jose Just [updated the answer](http://craftcms.stackexchange.com/posts/19258/revisions) to address the possibility of `supplier`/`product`/`delivery` params being blank.  

---

