How to use checkboxes to filter categories on the front end? i am trying to filter the various categories i have. Currently my url formats the following : www.site.com/news?cat=industry-news&amp;cat=architecture-design

I understand that i have to change this to a comma separated list but how do i do that and how do i make the filtering works so it does not only shows the first selected filter only?
here is my code:

`
{% set queryCategory = craft.request.getParam('cat') ?? '' %}
{% set categoryId = craft.categories.group('news').slug(queryCategory).first().id %}

{% paginate craft.entries.section('news').relatedTo(categoryId).limit(10) as entriesOnPage %}

&lt;form class="js-category"&gt;
{% set urlCategories = craft.request.getQueryString() %}
   {% for category in craft.categories.group('news') %}
     &lt;label class="filter__item" &gt;{{ category.title }}
   &lt;input {{ category.slug in urlCategories ? 'checked="checked"' : '' }}   name="cat" type="checkbox" value="{{category.slug}}"&gt;
    &lt;span class="filter__checkbox"&gt;&lt;/span&gt;
    &lt;/label&gt;
    {% endfor %}
&lt;/form&gt;`
Here is how I did it at my end for the templating side of things:


Set the queries you need and merge them into arrays like below. Please be aware this was done for craft commerce 2 products but the same can be applied to entries too as it is the same logic.


        {% set types = craft.categories.group('flowerTypes') %}
        {% set sizes = craft.categories.group('size') %}
        {% set prices = craft.categories.group('priceRanges') %}

        {% set flowersQuery = craft.app.request.getParam('flowers') | join(',') %}
        {% set sizeQuery = craft.app.request.getParam('size') | join(',') %}
        {% set priceQuery = craft.app.request.getParam('price') | join(',') %}

        {% set relationParam = [] %}
        {% set sizeParam = [] %}
        {% set flowersValues = [] %}
        {% set collectionValues = [] %}
        {% set sizeValues = [] %}
        {% set priceValues = [] %}

        {% set relationParam = ['and',{targetElement: category}] %}

        {% if flowersQuery != '' %}


            {% for queryFlower in flowersQuery|split(',') %}
              {% set flowerCategory = craft.categories.slug(queryFlower).one() %}
              {% set relationParam = relationParam|merge([{targetElement: flowerCategory}]) %}
              {% set flowersValues = flowersValues|merge([flowerCategory.title]) %}
            {% endfor %}
        {% endif %}

        {% if sizeQuery != '' %}


            {% for querySize in sizeQuery|split(',') %}
              {% set sizeCategory = craft.categories.slug(querySize).one() %}
              {% set sizeParam = sizeParam|merge([{targetElement: sizeCategory}]) %}
              {% set sizeValues = sizeValues|merge([sizeCategory.title]) %}
            {% endfor %}
        {% endif %}

        {% if priceQuery != '' %}


            {% for queryPrice in priceQuery|split(',') %}
              {% set priceCategory = craft.categories.slug(queryPrice).one() %}
              {% set relationParam = relationParam|merge([{targetElement: priceCategory}]) %}
            {% endfor %}
        {% endif %}

## this is where we set the query to grab the relational values

        {% set products = craft.products({
            relatedTo: relationParam,
            hasVariant: {
                relatedTo: sizeParam
            }
        }).status('live') %}



Set the markup for the filters, replace with whatever you use to do the front-end stuff


&lt;section id="filter-box" class="z-3 absolute site-bg w-100 dn"&gt;
    &lt;section class="z-3 relative w-100 left-0 site-bg pv4-ns"&gt;
        &lt;div class="container center"&gt;
            &lt;div class="flex flex-wrap flex-row justify-between items-start"&gt;
                &lt;div class="w-50-ns w-100 tl"&gt;
                    &lt;h1 class="large-header-text"&gt;All {{category.title}} Flowers&lt;/h1&gt;
                &lt;/div&gt;
                &lt;div class="w-50-ns w-100 tr"&gt;

                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class="flex-ns dn flex-wrap flex-row justify-between items-start pt4 h4-ns h-auto"&gt;
                &lt;div class="w-50-ns w-100 tl order-1-ns order-2 mb0-ns mb3"&gt;
                    &lt;div class="filtered is-closed"&gt;&lt;p class="ma0 dib v-mid"&gt;&lt;/p&gt;&lt;span class="filtered-amount ma0 dib v-mid"&gt;&lt;/span&gt;&lt;/div&gt;
                &lt;/div&gt;
                &lt;div class="w-50-ns w-100 db-ns dn tr order-2-ns order-1 mb0-ns mb3 flex flex-row flex-wrap justify-end"&gt;
                    {% include "_partials/buttons/filter" %}
                    {% include "_partials/buttons/clear_filters" %}
                &lt;/div&gt;
            &lt;/div&gt;

                &lt;form id="formTest" class="productFilter w-100 flex-ns flex-wrap flex-row justify-between items-start"&gt;
                    &lt;div class="mb3 mt2 Grid-cell text-gray pr3-ns flex-small h-auto-ns h2 overflow-visible-ns overflow-hidden"&gt;
                        &lt;div class="w-100 mb4 bb black-40 relative"&gt;
                            &lt;p class="ma0 title-medium-small db-ns dib mobileFilter"&gt;&lt;span class="dn-ns dib"&gt;Filter by&lt;/span&gt; Price&lt;/p&gt;
                            &lt;span class="dn-ns dib v-mid absolute right-0 top-0 bottom-0" style="line-height: 1.4em;"&gt;
                                &lt;svg width="14" height="14" class="svg-blue v-mid db h-100"&gt;
                                    &lt;use class="no-barba" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/icons.svg#arrow_down"&gt;&lt;/use&gt;
                                &lt;/svg&gt;
                            &lt;/span&gt;
                        &lt;/div&gt;
                        &lt;div id="selectedFilters" class="dib v-mid"&gt;
                            &lt;fieldset class="pa0 ma0 bw0"&gt;
                                &lt;p class="mb1 dn input-style"&gt;&lt;label class="pa0 ma0 lh-copy pointer bw1 br0"&gt;&lt;input value="all-prices" class="input-reset checked-filters" type="checkbox" name="collections[]"&gt;All prices&lt;/label&gt;&lt;/p&gt;
                                {% for p in prices.all() %}

                                    &lt;div class="ma0 input-style w-100-ns relative checkbox-style"&gt;
                                        &lt;input value="{{ p.slug }}" data-value="{{p.title}}" class="absolute left-0 top-0 h-100 w-100 input-reset checked-filters ttc z-2" type="checkbox" name="price[]" {% if p.slug in priceQuery %}checked{% endif %}&gt;&lt;label class="z-1"&gt;{{p.title}}&lt;/label&gt;
                                    &lt;/div&gt;

                                {% endfor %}
                            &lt;/fieldset&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div class="mb3 mt2 Grid-cell text-gray pr3-ns flex-medium h-auto-ns h2 overflow-visible-ns overflow-hidden"&gt;
                        &lt;div class="w-100 mb4 bb black-40 relative"&gt;
                            &lt;p class="ma0 title-medium-small db-ns dib mobileFilter"&gt;&lt;span class="dn-ns dib"&gt;Filter by&lt;/span&gt; Size&lt;/p&gt;
                            &lt;span class="dn-ns dib v-mid absolute right-0 top-0 bottom-0" style="line-height: 1.4em;"&gt;
                                &lt;svg width="14" height="14" class="svg-blue v-mid db h-100"&gt;
                                    &lt;use class="no-barba" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/icons.svg#arrow_down"&gt;&lt;/use&gt;
                                &lt;/svg&gt;
                            &lt;/span&gt;
                        &lt;/div&gt;
                        &lt;div id="selectedFilters" class="dib v-mid"&gt;
                            &lt;fieldset class="pa0 ma0 bw0"&gt;
                                &lt;p class="mb1 dn input-style"&gt;&lt;label class="pa0 ma0 lh-copy pointer bw1 br0"&gt;&lt;input value="all-sizes" class="input-reset checked-filters" type="checkbox" name="collections[]"&gt;All sizes&lt;/label&gt;&lt;/p&gt;
                                {% for s in sizes.all() %}

                                    &lt;div class="ma0 input-style w-100-ns relative checkbox-style"&gt;
                                        &lt;input value="{{ s.slug }}" data-value="{{s.title}}" class="absolute left-0 top-0 h-100 w-100 input-reset checked-filters ttc z-2" type="checkbox" name="size[]" {% if s.slug in sizeQuery %}checked{% endif %}&gt;&lt;label class="z-1"&gt;{{s.title}}&lt;/label&gt;
                                    &lt;/div&gt;

                                {% endfor %}
                            &lt;/fieldset&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div class="mb3 mt2 Grid-cell text-gray pr3-ns flex-large h-auto-ns h2 overflow-visible-ns overflow-hidden"&gt;
                        &lt;div class="w-100 mb4 bb black-40 relative"&gt;
                            &lt;p class="ma0 title-medium-small db-ns dib mobileFilter"&gt;&lt;span class="dn-ns dib"&gt;Filter by&lt;/span&gt; Flower type&lt;/p&gt;
                            &lt;span class="dn-ns dib v-mid absolute right-0 top-0 bottom-0" style="line-height: 1.4em;"&gt;
                                &lt;svg width="14" height="14" class="svg-blue v-mid db h-100"&gt;
                                    &lt;use class="no-barba" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/icons.svg#arrow_down"&gt;&lt;/use&gt;
                                &lt;/svg&gt;
                            &lt;/span&gt;
                        &lt;/div&gt;
                        &lt;div id="selectedFilters" class="dib v-mid w-100"&gt;
                            &lt;div class="pa0 ma0 bw0 flex flex-row flex-wrap w-100"&gt;
                                &lt;div class="ma0 input-style w-third-ns w-100 relative checkbox-style dn"&gt;
                                    &lt;input value="all-types" class="absolute left-0 top-0 h-100 w-100 input-reset checked-filters ttc z-2" type="checkbox" name="flowers[]"&gt;
                                    &lt;label class="z-1"&gt;All flowers&lt;/label&gt;
                                &lt;/div&gt;
                                {% for t in types.all() %}

                                    &lt;div class="ma0 input-style w-third-ns w-100 relative checkbox-style"&gt;
                                        &lt;input value="{{ t.slug }}" data-value="{{t.title}}" class="absolute left-0 top-0 h-100 w-100 input-reset checked-filters ttc z-2" type="checkbox" name="flowers[]" {% if t.slug in flowersQuery %}checked{% endif %}&gt;&lt;label class="z-1"&gt;{{t.title}}&lt;/label&gt;
                                    &lt;/div&gt;

                                {% endfor %}
                            &lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;

                &lt;/form&gt;

        &lt;/div&gt;
    &lt;/section&gt;
&lt;/section&gt;


Then with this it builds the url query for you to grab the products/entries you need from the url.

I then use a bit of js to manipulate the url to append the checked values to the url and do Ajax to get the entries:


site.getProducts = function(url) {

            const requestUrl = url;

                const productWrapper = document.getElementById('productWrapper')
                addClass(productWrapper, 'loading')


                $.ajax({
                    type: 'get',
                    url: requestUrl
                })
                  .fail(function( jqXHR, response ) {

                    const errorMsg = jqXHR.responseText

                  })
                  .done(function( response ) {

                    var parsedResponse = $.parseHTML(response);
                    var result = $(parsedResponse).find("#productWrapper .product-container"),
                        amount = $(parsedResponse).find("#filtered-area").data('product-count');

                    removeClass(productWrapper, 'loading')

                    loadedProductCount = amount;

                    if(!loadedProductCount &gt; 0){
                        $('.product-count').parent().html('No products match your filters.');
                        $('#filtered-area').addClass('vh-100');
                    } else {
                        $('#open-filter').html('See &lt;span class="product-count"&gt;'+loadedProductCount+'&lt;/span&gt; results');
                        $('#open-filter').css({
                            'borderColor': '',
                            'borderWidth': '',
                            'borderStyle': '',
                            'color': ''
                        });
                        $('#filtered-area').removeClass('vh-100');
                    }


                    $('#productWrapper').html(result);


                  });

};



site.addUrlQuery = function(event) {

        var collections = '',
            flowers = '',
            size = '',
            price = '',
            tempArray = [],
            mergedArray = [];

        var checkedFlowers, checkedSize, checkedCollections, checkedPrice;
        const node = document;
        checkedCollections = node.querySelectorAll('input[name="collections[]"]:checked');
        checkedFlowers = node.querySelectorAll('input[name="flowers[]"]:checked');
        checkedSize = node.querySelectorAll('input[name="size[]"]:checked');
        checkedPrice = node.querySelectorAll('input[name="price[]"]:checked');

        const arrCollections = Array.prototype.map.call(checkedCollections, function (e) {return e.value;}),
              arrFlowers = Array.prototype.map.call(checkedFlowers, function (e) {return e.value;}),
              arrPrice = Array.prototype.map.call(checkedPrice, function (e) {return e.value;}),
              arrSize = Array.prototype.map.call(checkedSize, function (e) {return e.value;});

        mergedArray.push(arrCollections+arrFlowers);

        tempArray.push(arrCollections);

        if(tempArray.length !== 0){
         collections+='collections='+tempArray.toString();
         tempArray = [];
        }

        tempArray.push(arrFlowers);

        if(tempArray.length !== 0){
         flowers+='flowers='+tempArray.toString();
         tempArray = [];
        }

        tempArray.push(arrPrice);

        if(tempArray.length !== 0){
         price+='price='+tempArray.toString();
         tempArray = [];
        }

        tempArray.push(arrSize);

        if(tempArray.length !== 0){
         size+='size='+tempArray.toString();
         tempArray = [];
        }

        // const url = '?'+collections+'&amp;'+flowers,
        //    requestUrl = url;

        const url = '?'+collections+'&amp;'+flowers+'&amp;'+price+'&amp;'+size,
                requestUrl = url;

        window.history.pushState('', '', url);

        if(url.indexOf('?') != -1){

            site.getProducts(url);

        }

};

var cboxArray = [];
let checkItems = '';

  function itemExistsChecker(cboxValue) {

    var len = cboxArray.length;

    if (len &gt; 0) {
      for (var i = 0; i &lt; len; i++) {
        if (cboxArray[i] == cboxValue) {
          return true;
        }
      }
    }

    cboxArray.push(cboxValue);

  } 

  $(".checked-filters").each(function() {

    var cboxValue = $(this).data('value');
    if(window.location.href.indexOf('?') != -1){
        var cboxChecked = null;
    } else {
        var cboxChecked = localStorage.getItem(cboxValue) == 'true' ? true : false;
    }

   //On page load check if any of the checkboxes has previously been selected and mark it as "checked"
    if (cboxChecked) {

      $(this).prop('checked', true);
      itemExistsChecker(cboxValue);

    }

    // On checkbox change add/remove the value from the array based on the choice
    $(this).change(function() {

        site.addUrlQuery();     

        localStorage.setItem(cboxValue, $(this).is(':checked'));

        if ($(this).is(':checked')) {

            itemExistsChecker(cboxValue);

        } else {

            // Delete the vehicle value from the array if its checkbox is unchecked
            var cboxValueIndex = cboxArray.indexOf(cboxValue);

            if (cboxValueIndex &gt;= 0) {
              cboxArray.splice( cboxValueIndex, 1 );
            }

        }

        if(cboxArray.length &gt; 1){ 
            checkItems = cboxArray.length +' filters selected' 
        } else { 
            checkItems = cboxArray.length +' filters selected' 
        }

        $('.filtered p').html(cboxArray.join(", "));
        $('.filtered-amount').html( checkItems );

    });

  });


    if(cboxArray.length &gt; 1){ 
        checkItems = cboxArray.length +' filters selected' 
    } else { 
        checkItems = cboxArray.length +' filters selected' 
    }

    $('.filtered p').html(cboxArray.join(", "));
    $('.filtered-amount').html( checkItems );


    $('.product-count').html(loadedProductCount);


I really hope this gets you on your way here.

Any q's please mention me and ask.