Skip to main content

Multiple filters with tags

Extension de la classe MultipleChoicesFilters. Cette extension vous permet de facilement ajouter des tags pour les options sélectionnées de vos filtres. Vous pouvez décider de placer les tags où vous voulez. Ils peuvent être sous chaque filtre ou dans un même div. L'attribut data-tags-row, que vous ajoutez sur chaque input spécifie le id du div où vous souhaitez afficher le tag.

Le template de votre tag est tiré d'une balise <template>. Cela vous permet de modifier facilement la structure html de votre tag sans toucher à la fonction JavaScript.

Demo

Colors
Types

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 { MultipleFiltersWithTags } from "@overdog/fn"

Instance et initialisation

new MultipleFiltersWithTags("#filter-wrapper-tags", {
   divIds: ["listing"]
}).init()
Cet élément utilise les mêmes options et arguments que le Multiple choices filters.

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

{% if relatedTo|length > 1 %}
  {% set relatedTo = ['and']|merge(relatedTo) %}
{% endif %}

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

{% set foodQuery = craft.entries()
  .section('structureFood')
  .orderBy('title')
  .relatedTo(relatedTo ? relatedTo : null)
  .with(['structureFoodColors', 'structureFoodTypes'])
  .all()
%}

{# --------------------- FETCH CATEGORIES GROUP AND RADIO BUTTON FIELD TO POPULATE FILTERS #}

{# categories group - example #}
{% set colorsCatGroup = craft.categories().group('groupFoodColors').select(['title', 'slug']).asArray().all() %}
{% set typesCatGroup = craft.categories().group('groupFoodTypes').select(['title', 'slug']).asArray().all() %}

{# --------------------- FILTER LAYOUT #}

{# ID is used by Javascript - a wrapper around your form is necessary as elem for your instance #}
<div id="filter-wrapper-tags" class="border border-gray-300 p-8 grid grid-cols-1 md:grid-cols-3 gap-half mb-half">

   {#  MACRO TAGS SECTION #}
   {% macro tag(id = "", content = "Category Name") %}
      <div 
      class="inline-flex items-center bg-[#c4cad2] rounded-xl cursor-pointer text-0.6em mr-10px mt-1 px-3 py-1 first:mt-8" 
      data-fn-tag-id="{{ id }}"
      >
         {# you can replace the SVG with one from your SVG Sprite #}
         <svg class="h-2 w-2 mr-4px shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
          </svg>
         <div data-fn-tag-content>{{ content }}</div>
      </div>
   {% endmacro %}
   
   {#  IMPORTANT : HTML TEMPLATE FOR THE TAGS SECTION #}
   {# template for tags - used by JS - not rendered by the browser #}
   <template data-fn-tag-template>
      {{ _self.tag() }}
   </template>  

  {# COLORS FILTER #}
  {% if colorsCatGroup|length %}
    <form data-fn-filter-group="{{ colorsUrlQueryName }}">
      <fieldset>
        <legend class="font-bold mb-quarter">{{ 'Colors'|t }}</legend>
        {% for cat in colorsCatGroup %}
         <div class="flex items-center relative py-1">
            <input 
               id="{{ cat.slug }}"
               class="inset-0 opacity-0 absolute -z-1 peer"
               data-fn-tag-row="tag-row-colors"
               type="checkbox" 
               name="{{ cat.slug }}" 
               value="{{ cat.slug }}"
               {{(cat.slug in colorsUrlQueryValue) ? '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="{{ cat.slug }}"
            >{{ cat.title }}</label>
         </div>
        {% endfor %}
      </fieldset>

      {# TAGS ROW with initial content to show tags on page load #}
      <div id="tag-row-colors">
         {% if colorsUrlQueryValue|length %}
            {% for cat in colorsCatGroup|filter(cat => cat.slug in colorsUrlQueryValue) %}
               {{ _self.tag(cat.slug, cat.title) }}
            {% endfor %}
         {% endif %}
      </div>

    </form>
  {% endif %}

  {# TYPES FILTER #}
  {% if typesCatGroup|length %}
    <form data-fn-filter-group="{{ typesUrlQueryName }}">
      <fieldset>
        <legend class="font-bold mb-quarter">{{ 'Types'|t }}</legend>
        {% for cat in typesCatGroup %}
         <div class="flex items-center relative py-1">
               <input 
                  id="{{ cat.slug }}"
                  class="inset-0 opacity-0 absolute -z-1 peer"
                  data-fn-tag-row="tag-row-types"
                  type="checkbox" 
                  name="{{ cat.slug }}" 
                  value="{{ cat.slug }}" 
                  {{(cat.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="{{ cat.slug }}"
               >{{ cat.title }}</label>
         </div>
        {% endfor %}
      </fieldset>

      {# TAGS ROW with initial content to show tags on page load #}
      <div id="tag-row-types">
         {% if typesUrlQueryValue|length %}
            {% for cat in typesCatGroup|filter(cat => cat.slug in typesUrlQueryValue) %}
               {{ _self.tag(cat.slug, cat.title) }}
            {% endfor %}
         {% endif %}
      </div>

    </form>
  {% 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>