Skip to main content

Single choice filter

Demo

Installation

Import the function into the JavaScript file of your project

import { SingleFilter } from "@overdog/fn"
Note: You need to combine filters with the dropdown element to achieve the look of this demo. Your forms will be placed inside dropdowns.

Create and initialize an instance

new SingleFilter("#form-categories", {
   divIds: ["listing"]
}).init()

Twig template Code

{# --------------------- CONTENT MAIN QUERY #}

{# if category is defined, show only entries relatedTo this category #}
{% set foodQuery = craft.entries()
  .section('structureFood')
  .with(['structureFoodColors', 'structureFoodTypes'])
  .relatedTo((category is defined) ? category.id : null)
  .all()
%}

{# --------------------- FILTER BAR #}

{# query categories with relatedTo to your section if you want ONLY the categories associated to the entries #}
{% set colorsCatGroup = craft.categories().group('groupFoodColors').all() %}
{% set catInUrl = craft.app.request.getSegment(-1) %} {# get the last url segment - see docs if need more control #}

<div class="">
  {# Dropdown filter single choice #}
  {% if colorsCatGroup|length %}
    <div class="filter-dropdown max-w-[500px] relative mb-half">
      <button 
         class="flex items-center border-b border-[#a5adb9] h-[50px] justify-between text-left w-full"
         aria-expanded="false"
         aria-controls="filter-category"
      >
        <span data-fn-dropdown-text>{{ 'Filter by category'|t }}</span>
            {# caret #}
            <span class="
            border-b-0 border-x-transparent border-x-[0.3em] border-t-[0.3em] border-t-slate-600
            transition-all ease-linear duration-200
            group-hover:text-red
            parent-is-open:rotate-180 parent-is-open:text-red
            ">
         </span>
      </button>
      <div
         id="filter-category" {# only for aria-controls - not used by JS #}
         class="absolute hidden left-0 bg-white rounded-b-md shadow-md overflow-hidden w-full z-10
         parent-is-open:block
      ">
        <form id="form-categories">
          <fieldset>
            <legend class="sr-only">{{ 'Filter by category'|t }}</legend>
            <div>
               <input 
                  id="all"
                  class="absolute inset-0 opacity-0 -z-1"
                  type="radio" 
                  name="cat-radio" 
                  value="{{ siteUrl }}/single-choice-filter"
               />
               <label class="cursor-pointer block px-3.5 py-1.5 w-full hover:bg-[#e7edee]" for="all">{{ 'All colors'|t }}</label>
            </div>
            {% for category in colorsCatGroup %}
              {# name must be the same for radio button #}
               <div>
                  <input 
                     id="{{ category.slug }}" 
                     class="absolute inset-0 opacity-0 -z-1" 
                     type="radio" 
                     name="cat-radio" 
                     value="{{ category.url }}" {{(category.slug in catInUrl) ? 'checked' }}
                  />
                  <label class="cursor-pointer block px-3.5 py-1.5 w-full hover:bg-[#e7edee]" for="{{ category.slug }}">{{ category.title }}</label>
               </div>
            {% endfor %}
          </fieldset>
        </form>
      </div>
    </div>
  {% endif %}
</div>


{# --------------------- CONTENT AND LOOP #}

<div id="listing" class="grid grid-col-1 md:grid-cols-3 gap-third opacity-1 is-loading:opacity-40 transition-opacity">
   {% if foodQuery|length %}
      {{ include('_lib-fn/_card', { queryName: foodQuery }, ignore_missing = true )}}
   {% else %}
      <div>{{ ('There is no content matching your criteria.')|t }}</div>
   {% endif %}
</div>

Options