Previous
Autocomplete
import { MultipleFilters } from "@overdog/fn"
new MultipleFilters("#filter-wrapper-multiple", {
divIds: ["listing"],
clearAllButtonId: "clear-all"
}).init()
{# --------------------- SET RELATEDTO ARRAY #}
{% set relatedTo = [] %}
{# --------------------- FETCH CATEGORIES GROUP AND RADIO BUTTON FIELD TO POPULATE FILTERS #}
{# categories group - example #}
{% set colorsCatGroup = craft.categories().group('groupFoodColors').all() %}
{% set typesCatGroup = craft.categories().group('groupFoodTypes').all() %}
{# radio field - example #}
{% set radioField = craft.app.fields.getFieldByHandle('structureFoodAvailability') %}
{# --------------------- 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 relatedColorsCats = colorsCatGroup|filter(cat => cat.slug in colorsUrlQueryValue) %}
{% set relatedTo = relatedTo|merge([{ targetElement: relatedColorsCats }]) %}
{% 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 relatedTypesCats = typesCatGroup|filter(cat => cat.slug in typesUrlQueryValue) %}
{% set relatedTo = relatedTo|merge([{ targetElement: relatedTypesCats }]) %}
{% endif %}
{# --------------------- RADIO BUTTON FIELD 3 - AVAILABILITY
no need to split param - radio button always give one value at the time (same thing with a select input)
#}
{% set availabilityUrlQueryName = 'availability'|t %} {# variable also used in the form name #}
{% set availabilityUrlQueryValue = craft.app.request.getQueryParam(availabilityUrlQueryName) %}
{# --------------------- SEARCH INPUT 4 #}
{% set searchUrlQueryName = 'keyword'|t %}
{% set searchUrlQueryValue = craft.app.request.getQueryParam(searchUrlQueryName) %}
{# --------------------- MERGE THE CATEGORIES FOR THE MAIN QUERY RELATEDTO #}
{% if relatedTo|length > 1 %}
{% set relatedTo = ['and']|merge(relatedTo) %}
{% endif %}
{# --------------------- MAIN QUERY #}
{% set foodQuery = craft.entries()
.section('structureFood')
.orderBy('title')
.relatedTo(relatedTo ? relatedTo : null)
.search(searchUrlQueryValue)
.with(['structureFoodColors', 'structureFoodTypes'])
.structureFoodAvailability(availabilityUrlQueryValue ?? null)
.all()
%}
{# --------------------- FILTER LAYOUT #}
{# ID is used by Javascript - a wrapper around your form is necessary > see docs #}
<div id="filter-wrapper-multiple" class="grid grid-cols-1 md:grid-cols-3 gap-half mb-half">
{# COLORS FORM -> checkbox - category #}
{% 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
class="inset-0 opacity-0 absolute -z-1 peer"
id="{{ cat.slug }}"
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-gray-200 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>
</form>
{% endif %}
{# TYPES FORM -> checkbox - category #}
{% 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
class="inset-0 opacity-0 absolute -z-1 peer"
id="{{ cat.slug }}"
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-gray-200 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>
</form>
{% endif %}
{# AVAILABILITY FORM -> radio button - field #}
<form data-fn-filter-group="{{ availabilityUrlQueryName }}">
<fieldset>
<legend class="font-bold mb-quarter">Radio Button Field</legend>
<div class="flex items-center relative py-1">
{# HINT : name on all input must be the SAME for radio button #}
<input
id="all"
class="inset-0 opacity-0 absolute -z-1 peer"
type="radio"
name="availability"
value=""
/>
<label
class="cursor-pointer flex items-center w-full
peer-checked:before:bg-black
before:bg-gray-200 before:rounded-full before:cursor-pointer before:inline-block before:h-4 before:w-4 before:mr-4 before:shrink-0"
for="all"
>
{{ 'All availabilities'|t }}
</label>
</div>
{% for option in radioField.options %}
<div class="flex items-center relative py-1">
{# HINT : name on all input must be the SAME for radio button #}
<input
id="{{ option.value }}"
class="inset-0 opacity-0 absolute -z-1 peer"
type="radio"
name="availability"
value="{{ option.value }}" {{(option.value in availabilityUrlQueryValue) ? 'checked' }}
/>
<label
class="cursor-pointer flex items-center w-full
peer-checked:before:bg-black
before:bg-gray-200 before:rounded-full before:cursor-pointer before:inline-block before:h-4 before:w-4 before:mr-4 before:shrink-0"
for="{{ option.value }}"
>
{{ option.label }}
</label>
</div>
{% endfor %}
</fieldset>
</form>
{# SEARCH FORM > The role search on the form is needed by JS #}
<form role="search" class="flex md:col-span-2 max-w-[600px]" data-fn-filter-group="{{ searchUrlQueryName }}">
<div class="h-[44px] relative w-full">
<input
class="border-b border-gray-300 h-full px-4 w-full"
type="text"
name="{{ searchUrlQueryName }}"
autocomplete="off"
placeholder="Search.."
>
{# searchbox reset #}
<input class="text-[#999] cursor-pointer text-[13px] h-full absolute right-0 px-4" type="reset" value="delete">
</div>
<button
class="rounded-full shrink-0 text-0.9em h-[44px] ml-4 w-[44px] bg-slate-700 text-white"
type="submit"
value="submit"
>
Go
</button>
</form>
<button id="clear-all" type="reset" value="clear">clear all</button>
</div>
{# --------------------- LAYOUT WIH LOOP FOR CARDS #}
{# ID is used by Javascript - The div must be always visible (do not wrap an If condition around) #}
<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>