Suppose you already have a working Finsweet filter setup with two dropdowns working. Wouldn’t it be nice if the second dropdown only shows those options that have elements with the first dropdowns selected option.
As a demo I will use a small example project. It displays a list of cars, which is filterable by the cars type and their brand. Try it yourself or Clone it here.
Let’s first look at the structure of our page in Webflow. We give our two select elements unique classes, so we can identify them later in code.
For our collection list we need to identify the whole collection list and its individual items. It is also important that we can identify the attributes we want to filter by.
That is all that needs to be done in Webflow, so now let’s look at the code.
First we need to grab our two select elements and listen for the change event on one of them.
We also save our collection list items, because the Finsweet filter will dynamically add and remove list items from the DOM.
const typeSelect = document.querySelector('.filter-form-select.type');
const brandSelect = document.querySelector('.filter-form-select.brand');
const items = Array.from(document.querySelectorAll('.collection-list .collection-list-item')); // Get all collection items
typeSelect.addEventListener('change', updateBrands); // Update when type selection changes
Before we look at the implementation of the updateBrands method, we will write ourselves a handy little helper method to display only specific options in our brand select.
This method takes an array of the option values that should be displayed as a parameter.
Loop through all option elements in the brand select element.
If the option has no value, the default option, ignore it. It should always be displayed.
If the brands array does not contain this option’s value, it should be hidden.
Set the hidden attribute accordingly.
Some browsers (e.g. Safari) do not support hidden on an option element. As a fallback, set the disabled attribute too. Disabled options cannot be selected and most likely appear greyed out.
After that is out of the way, we can start to implement our updateBrands method.
First we will cover what happens, when no type is selected. All brands should be displayed.
We get all available options from the brand select element and convert them to an array. Then we map these option elements to their value attributes. We now have an array of all available values.
Lastly we just give this array to our displayBrands method and it will show all option elements.
Now let’s look at what happens when there is a type selected
We transform the array of list items we saved early to an array of the brands we want to display.
First we filter for items that have the same type as the selected type
We get the corresponding type for each item by querying for the .type class.
If the type is the same as the selected, return true to include this item.
Now we map each of the items to their brands which should be displayed.
So we return the brand value, by querying for the .brand class.
At the end call our displayBrands method again, to show all brands that have at least some items with the selected type.
And that’s it! The second filter dropdown now only displays options that make sense for the selected option of the first filter dropdown. Here’s the full code
const typeSelect = document.querySelector('.filter-form-select.type');
const brandSelect = document.querySelector('.filter-form-select.brand');
typeSelect.addEventListener('change', updateBrands); // Update when type selection changes
function updateBrands() {
const selectedType = typeSelect.value;
if (!selectedType) { // If no type is selected display all brands
const allBrands = Array.from(brandSelect.options).map(option => option.value); // Get all available options and convert them to their values
displayBrands(allBrands); // Display all brands that are in the select field
} else {
const items = Array.from(document.querySelectorAll('.collection-list .collection-list-item')); // Get all collection items
// Transform to available brands in selected type
const brands = items.map(item => {
const type = item.querySelector('.type').textContent; // Get type of the item
if (type === selectedType) { // If this type is selected, return the brand to add it to the list
return item.querySelector('.brand').textContent;
} // If this type is not selected, return nothing and ignore this item
});
displayBrands(brands); // Display all the brands that have the selected type
}
}
function displayBrands(brands) {
brandSelect.querySelectorAll('option').forEach(option => {
if (!option.value) return; // Skip default option without value
const hidden = !brands.includes(option.value);
option.hidden = hidden;
option.disabled = hidden;
});
}
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.