Demo
Ananas
Brun
Jaune
Fruits
Avocat
Vert
Fruits
Banane
Jaune
Fruits
Brocoli
Vert
Légumes
Celeri
Vert
Légumes
Citron
Jaune
Fruits
Filet mignon
Gris
Viande
Lime
Vert
Fruits
Patate
Brun
Jaune
Légumes
Pomme
Rouge
Fruits
Salade
Vert
Légumes
Steak
Rouge
Viande
Installation
Importez la fonction dans votre projet
import { MultipleFilters } from "@overdog/fn"
Note : Vous devez combiner les filtres avec l'élément dropdown pour avoir le look de ce démo. Vos forms se retrouveront dans des dropdowns.
Instance et initialisation
new MultipleFilters("#filter-wrapper-multiple-dropdown", {
divIds: ["listing"]
}).init()
Twig template Code
{# --------------------- SET RELATEDTO ARRAY #}
{% set relatedTo = [] %}
{# --------------------- CATEGORY GROUP 1 - COLORS #}
{% set colorsUrlQueryName = 'colors'|t %} {# variable also used in the form name #}
{% set colorsUrlQueryValue = craft.app.request.getQueryParam(colorsUrlQueryName)|split(',')|filter %}
{% if colorsUrlQueryValue %}
{% set relatedTo = relatedTo|merge([{
targetElement: craft.categories({ group: 'groupFoodColors', slug: colorsUrlQueryValue }).ids()
}]) %}
{% endif %}
{# --------------------- CATEGORY GROUP 2 - TYPES #}
{% set typesUrlQueryName = 'types'|t %} {# variable also used in the form name #}
{% set typesUrlQueryValue = craft.app.request.getQueryParam(typesUrlQueryName)|split(',')|filter %}
{% if typesUrlQueryValue %}
{% set relatedTo = relatedTo|merge([{
targetElement: craft.categories({ group: 'groupFoodTypes', slug: typesUrlQueryValue }).ids()
}]) %}
{% endif %}
{# --------------------- MERGE THE CATEGORIES FOR THE RELATEDTO #}
{% if relatedTo|length > 1 %}
{% set relatedTo = ['and']|merge(relatedTo) %}
{% endif %}
{# --------------------- MAIN QUERY - with eager loading the categories #}
{% set foodQuery = craft.entries()
.section('structureFood')
.orderBy('title')
.relatedTo(relatedTo ? relatedTo : null)
.with(['structureFoodColors', 'structureFoodTypes'])
.all()
%}
{# --------------------- FETCH CATEGORIES GROUP TO POPULATE FILTERS #}
{# categories group #}
{% set typesCatGroup = craft.categories().group('groupFoodTypes').all() %}
{% set colorsCatGroup = craft.categories().group('groupFoodColors').all() %}
{# --------------------- FILTERS LAYOUT #}
{# ID is used by Javascript #}
<div id="filter-wrapper-multiple-dropdown" class="grid grid-cols-1 md:grid-cols-3 gap-half mb-half">
{# TYPES FORM - Dropdown filter multiple choices #}
{% if typesCatGroup|length %}
<div class="filter-dropdown relative">
<button
class="flex items-center border-b border-[#a5adb9] h-[50px] justify-between text-left w-full"
aria-expanded="false"
aria-controls="form-type"
>
<span>{{ 'Filter by type'|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
parent-is-open:rotate-180
">
</span>
</button>
<div
id="form-types" {# only for aria-controls - not used by JS #}
class="absolute hidden left-0 p-4 bg-white rounded-b-md shadow-md overflow-hidden w-full z-10
parent-is-open:block"
>
<form data-fn-filter-group="{{ typesUrlQueryName }}">
<fieldset>
<legend class="sr-only">{{ 'Filter by type'|t }}</legend>
{% for category in typesCatGroup %}
<div class="flex items-center relative py-1">
<input
id="{{ category.slug }}"
class="inset-0 opacity-0 absolute -z-1 peer"
type="checkbox"
name="{{ category.slug }}"
value="{{ category.slug }}" {{(category.slug in typesUrlQueryValue) ? 'checked' }}
/>
<label
class="cursor-pointer flex items-center w-full
peer-checked:before:bg-black
before:bg-[#c4cad2] before:cursor-pointer before:inline-block before:h-4 before:w-4 before:mr-4 before:shrink-0"
for="{{ category.slug }}"
>
{{ category.title }}
</label>
</div>
{% endfor %}
</fieldset>
</form>
</div>
</div>
{% endif %}
{# COLORS FORMS - Dropdown filter fake select single choice #}
{% if colorsCatGroup|length %}
<div class="filter-dropdown relative">
<button
class="flex items-center border-b border-[#a5adb9] h-[50px] justify-between text-left w-full"
aria-expanded="false"
aria-controls="form-colors"
>
<span data-fn-dropdown-text>{{ 'Filter by colors'|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
parent-is-open:rotate-180
">
</span>
</button>
<div
id="form-colors" {# 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 data-fn-filter-group="{{ colorsUrlQueryName }}">
<fieldset>
<legend class="sr-only">{{ 'Filter by colors'|t }}</legend>
<div>
<input
id="all"
class="absolute inset-0 opacity-0 -z-1"
type="radio"
name="cat-radio"
value=""
/>
<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.slug }}" {{(category.slug in colorsUrlQueryValue) ? '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>
{# --------------------- LAYOUT WIH LOOP FOR CARDS #}
{# ID is used by Javascript #}
<div id="listing" class="grid grid-col-1 md:grid-cols-3 gap-third">
{% 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>