Welcome to the next installment of our on-going "Tips" series - DIY tutorials for web developers and the casual coder.
For this example you'll need the basics:
We're going to build a list of items (in this case - events) that can be filtered by category.
We'll start by showing the 3 most recent events and let the user filter the full list of events by their location - creating a list that's more relevant to them.
Let's get started...
This will be the state seen by the user before any interaction occurs.
Below, we will:
.
<!-- create the select element -->
<select id="select_event_region">
<option>Select your region</option>
{% set myCategoryQuery = craft.categories().group('locationRegion') %}
{% set categories = myCategoryQuery.all() %}
{% for list in categories %}
<option value="{{ list.slug }}">{{ list.title }}</option>
{% endfor %}
</select>
<!-- initial query -->
{% set params = {
section : 'events',
order : 'eventDate asc',
eventDate : '>=' ~ 'now'|date('U'),
limit : '3'
} %}
<!-- get the entries -->
<div class="events">
{% if craft.entries(params)|length %}
{% for entry in craft.entries(params) %}
<h4>{{ entry.title }}</h4>
{% endfor %}
{% endif%}
</div>
Retrieve the user settings from the select element and set it as a variable for our include. Once we have the option from the select element, we'll turn it into a variable and store it in the url.
Below we will:
.
<!-- get the select option onChange. Save it as a variable we can retrieve from our include. -->
{% js %}
const base_url = '/ajax/events';
const $patient_events = $('.events');
$('#select_event_region').change(function() {
const region = this.value;
const url = (region.length) ? `${base_url}?region=${region}` : base_url;
$.get(url, function(response) {
$patient_events.html(response);
});
});
{% endjs %}
Let's quickly look at this line and how it sets up our ajax call:
const url = (region.length) ? `${base_url}?region=${region}` : base_url;
We're creating a constant array with a conditional that says: If the variable is set, generate the url with the region variable or else just use the base url. The use of back tick is for a string where you're inserting variables so you don't have concatenate using the plus sign.
This will be pulled into our original template via ajax when the user filters by region. We'll keep this out of the way in a folder called "ajax". Example: /ajax/events.html
Below we will:
.
<!-- Repeat original query but add the new variable -->
{% set params = { section: 'patientEvents', order: 'eventDate asc', endDate: '>' ~ 'now'|date('U') } %}
{% set region = craft.request.param('region') %}
{% set region_cat = craft.categories.group('locationRegion').slug(region).one %}
{% if region_cat %}
{% set params = params | merge({relatedTo: {targetElement: region_cat.id}}) %}
{% endif %}
<!-- Loop through the filtered entries -->
{% set entries = craft.entries(params) %}
{% if entries|length %}
{% for entry in entries.all %}
<h4>{{ entry.title }}</h4>
{% endfor %}
{% endif %}
Let's look at:
{% set region = craft.request.param('region') %}
craft.request.param is not well documented but it grabs the variable from our ajax request that we set up in Step 2.
And that's it! More than three steps would be too many :-)
Some ideas to enhance this might include adding a loading animation and handling a null result. If you have any ideas other you'd like to share for improving this or if you found it useful, please let us know in the comments.