Is there a way to filter the options in a form select, which are populated with CMS items?
For example:
Select 1: Contains a list of countries.
Select 2: Contains a list of cities.
If ‘New Zealand’ is chosen as a country in the first select field, could we then filter the options in the ‘Cities’ select field to include only cities within New Zealand?
Both of these selections are populated by CMS items.
Hello @Marko, this is not possible with the CMS attribute. Anyway, it can be achieved using a custom script.
Could you define to me how you determine which Cities are under a certain country, are they nested within the CMS item and I’ll see how we can come up with a custom script
Thanks @josephmukunga! The cities are catagorised using a reference field in the cms collection. The reference field is linked to the country collection. Let me know if you have any other questions. Thanks so much for taking a look.
@josephmukunga My apologies for the late reply. I became unwell and was away from my computer for quite some time. I’m a lot better now and glad to get back into it. Here are the links:
Thanks @josephmukunga! I really appreciate it! I’ve implemented the changes but have made a mistake somewhere as it’s not quite working. Can you see where I went wrong? Updated links are below:
@josephmukunga Hi, how are you? I apologise for the delayed response; I was preoccupied with another job. Thank you for sending the updated code! Very appreciated!
It seems to work for some items but not for all. Could you help me identify where I might be going wrong? For instance, it works for ‘Camera’.
EDIT: I’ve noticed that only the first set of pagination roles are loading in the ‘Role’ dropdown menu. How can I modify it to load all the roles? So far, I have added FinSweet’s CMS Load attribute with a render all added.
If you have used CMS Load to load your CMS Collection where you are generating the options you can wait until all items have finished loading and execute the script above inside the Attributes callback. The code would look something like this
<script>
window.fsAttributes = window.fsAttributes || [];
window.fsAttributes.push([
'cmsload',
(listInstances) => {
console.log('cmsload has finished laoding!');
const departments = document.querySelectorAll('[department="cms"] [department="text"]');
const rolesCMSItems = document.querySelectorAll('[role="cms"] [role="listitem"]');
const roles = Array.from(rolesCMSItems).map((cmsItem) => {
const role = {
role: cmsItem.querySelector('[role="text"]').innerText,
department: cmsItem.querySelector('[role="department"]').innerText,
};
return role;
});
let departmentDropdown = document.querySelector('[department="select"]');
for (var i = 0; i < departments.length; i++) {
const department = departments[i];
const departmentText = department.innerText;
let option = document.createElement('option');
option.value = departmentText;
option.textContent = departmentText;
departmentDropdown.appendChild(option);
}
// Function to filter roles based on department selection
function filterRoles() {
let roleDropdown = document.querySelector('[role="select"]');
let selectedDepartment = departmentDropdown.value;
// Clear previous options
roleDropdown.innerHTML = '';
// Filter roles based on selected department
let filteredRoles = roles.filter((role) => {
return selectedDepartment === 'all' || role.department === selectedDepartment;
});
// Populate role dropdown with filtered roles
for (var i = 0; i < filteredRoles.length; i++) {
var option = document.createElement('option');
option.value = filteredRoles[i].role;
option.textContent = filteredRoles[i].role;
roleDropdown.appendChild(option);
}
}
departmentDropdown.addEventListener('change', () => {
filterRoles();
});
},
]);
</script>