In a previous post I was helped a lot with some issues I have encountered while using Finsweet CMS Select & Filter. I am very grateful about the help I have received. But after installing the new code I was provided with, I couldn’t use the submit button of my form anymore. I have tried searching for hidden elements within the form with “required” still checked and checking if the “listInstances” are still on the right place (as far as I can tell).
Hello @Vible! I believe the issue might originate from the CMS Filter setup. If you were trying to filter the Select collections you can remove the script and the element attributes as the code I provided on the other thread will manage the filtering.
Another thing that may be worth looking at is the errors on the console after a user tries to submit the form
Thank you for your reply! The form seems to be working. Unfortunately, I have encountered a minor issue.
I am using the Query Param attribute for the form. My issue is as follows: for example, when a user visits the page with pre-selected options and tries to change the starting date or the course, the options in the select fields are no longer available. It seems as if the Query Param attribute prevents the select and filter attributes from being triggered.
Do you happen to know what might be causing this issue?
<script>
window.fsAttributes = window.fsAttributes || [];
window.fsAttributes.push([
'cmsselect',
(listInstances) => {
console.log('cmsselect successfully loaded!');
const eventSelect = document.querySelector('[fs-cmsselect-element="select"]');
const opleidingSelect = document.querySelector('[fs-cmsselect-element="select-2"]');
const startdatumSelect = document.querySelector('[fs-cmsselect-element="select-3"]');
const listInstance = listInstances[1];
const startdatumListInstance = listInstances[2];
const { items } = listInstance;
const { items: startdatumItems } = startdatumListInstance;
// Function to get query parameters from the URL
function getQueryParams() {
return Object.fromEntries(new URLSearchParams(window.location.search).entries());
}
// Function to populate form fields dynamically based on query parameters
function populateFormFields() {
const queryParams = getQueryParams();
// Loop through each query parameter
for (const [param, value] of Object.entries(queryParams)) {
// Try to find a form field by 'name', 'id', or custom attribute
const formField = document.querySelector(`[name="${param}"]`);
if (formField) {
if (formField.tagName === 'SELECT') {
// For select elements, match the value with one of the options
const optionToSelect = Array.from(formField.options).find(
(option) => option.value === value || option.textContent.trim() === value
);
if (optionToSelect) {
optionToSelect.selected = true;
}
} else {
// For other input types
formField.value = value;
}
}
}
}
// Function to create a placeholder element for the select
const createPlaceholder = (text) => {
const placeholder = document.createElement('option');
placeholder.value = '';
placeholder.textContent = text;
placeholder.selected = true;
return placeholder;
};
// Populate fields when the page loads
populateFormFields();
// Event handling for the event select
eventSelect.addEventListener('change', ({ target }) => {
const selectValue = target.value;
const filteredItems = items.filter(({ element }) => {
if (!selectValue) return true;
const textValue = element.querySelector('[fs-cmsselect-element]');
return textValue?.getAttribute('data-category') === selectValue;
});
opleidingSelect.innerHTML = '';
startdatumSelect.innerHTML = '';
opleidingSelect.appendChild(createPlaceholder('Kies een optie...'));
startdatumSelect.appendChild(createPlaceholder('Kies een optie...'));
filteredItems.forEach(({ element }) => {
const textValue = element.querySelector('[fs-cmsselect-element]');
if (textValue) {
const optionElement = document.createElement('option');
optionElement.value = optionElement.textContent = textValue.textContent.trim();
opleidingSelect.appendChild(optionElement);
}
});
});
// Event handling for the opleiding select
opleidingSelect.addEventListener('change', ({ target }) => {
const selectValue = target.value;
const filteredItems = startdatumItems.filter(({ element }) => {
if (!selectValue) return true;
const textValue = element.querySelector('[fs-cmsselect-element]');
return textValue?.getAttribute('data-category') === selectValue;
});
startdatumSelect.innerHTML = '';
startdatumSelect.appendChild(createPlaceholder('Kies een optie...'));
filteredItems.forEach(({ element }) => {
const textValue = element.querySelector('[fs-cmsselect-element]');
if (textValue) {
const optionElement = document.createElement('option');
optionElement.value = optionElement.textContent = textValue.textContent.trim();
startdatumSelect.appendChild(optionElement);
}
});
});
},
]);
</script>
Note that the way of creating the query params has changed; we need to set the parameter name exactly as we have the name for the field, as this is case-sensitive.
I hope you’ve been doing well! It’s been a while, and I hope you had a great holiday season. I apologize for not responding earlier—I was on vacation.
Thank you for providing the new custom query parameter code! Unfortunately, the filter and select still don’t seem to trigger after clicking on a query parameter link. For example:
I might be overlooking something in the code or the query parameter link, but I can’t seem to figure it out. When you mentioned the “name” for the parameter, did you mean the class name or the name we assigned in the attribute?
After these names match, we can actually remove the Query Params Attribute.
I also wanted to ask if you could please record a quick Loom on the expected flow for the form. I may also be overlooking something or misunderstanding the functionality you are trying to achieve.
The adjustment was what we needed, it’s working now! There’s only one final adjustment needed for the form to work as intended. I’ve made a Loom recording to explain what the final adjustment needs to be. In short: I want the first and second choices to be locked after clicking on the query parameter URL. In the recording I explain why.
Sure! I’ve updated the script with some minor tweaks, ie. if a query param is missing the user should be able to still select that option by themselves.
Can you add this and let me know if I am missing anything?
<script>
window.fsAttributes = window.fsAttributes || [];
window.fsAttributes.push([
'cmsselect',
(listInstances) => {
console.log('cmsselect successfully loaded!');
const categorySelect = document.querySelector('[name="Categorie"]');
const opleidingSelect = document.querySelector('[name="Opleiding"]');
const startdatumSelect = document.querySelector('[name="Startdatum"]');
const listInstance = listInstances[1];
const startdatumListInstance = listInstances[2];
const { items } = listInstance;
const { items: startdatumItems } = startdatumListInstance;
// Function to get query parameters from the URL
function getQueryParams() {
return Object.fromEntries(new URLSearchParams(window.location.search).entries());
}
// Function to create a placeholder element for the select
const createPlaceholder = (text) => {
const placeholder = document.createElement('option');
placeholder.value = '';
placeholder.textContent = text;
placeholder.disabled = true;
placeholder.selected = true;
return placeholder;
};
// Function to apply cascading filters programmatically
function applyCascadingFilters(queryParams) {
let isCategoryFiltered = false;
let isOpleidingFiltered = false;
// Trigger 'Categorie' filtering
if (queryParams.Categorie) {
const categoryOption = Array.from(categorySelect.options).find(
(option) => option.textContent.trim() === queryParams.Categorie
);
if (categoryOption) {
categoryOption.selected = true;
// Filter 'Opleiding'
const filteredItems = items.filter(({ element }) => {
const textValue = element.querySelector('[fs-cmsselect-element]');
return textValue?.getAttribute('data-category') === queryParams.Categorie;
});
opleidingSelect.innerHTML = '';
startdatumSelect.innerHTML = ''; // Reset 'Startdatum'
opleidingSelect.appendChild(createPlaceholder('Kies een optie...'));
startdatumSelect.appendChild(createPlaceholder('Kies een optie...'));
filteredItems.forEach(({ element }) => {
const textValue = element.querySelector('[fs-cmsselect-element]');
if (textValue) {
const optionElement = document.createElement('option');
optionElement.value =
textValue.getAttribute('data-value') || textValue.textContent.trim();
optionElement.textContent = textValue.textContent.trim();
opleidingSelect.appendChild(optionElement);
}
});
categorySelect.disabled = true; // Disable 'Categorie'
isCategoryFiltered = true;
}
}
// Trigger 'Opleiding' filtering
if (queryParams.Opleiding && isCategoryFiltered) {
const opleidingOption = Array.from(opleidingSelect.options).find(
(option) => option.textContent.trim() === queryParams.Opleiding
);
if (opleidingOption) {
opleidingOption.selected = true;
// Filter 'Startdatum'
const filteredItems = startdatumItems.filter(({ element }) => {
const textValue = element.querySelector('[fs-cmsselect-element]');
return textValue?.getAttribute('data-category') === queryParams.Opleiding;
});
startdatumSelect.innerHTML = '';
startdatumSelect.appendChild(createPlaceholder('Kies een optie...'));
filteredItems.forEach(({ element }) => {
const textValue = element.querySelector('[fs-cmsselect-element]');
if (textValue) {
const optionElement = document.createElement('option');
optionElement.value =
textValue.getAttribute('data-value') || textValue.textContent.trim();
optionElement.textContent = textValue.textContent.trim();
startdatumSelect.appendChild(optionElement);
}
});
opleidingSelect.disabled = true; // Disable 'Opleiding'
isOpleidingFiltered = true;
}
}
// Handle cases where 'Opleiding' query param is missing
if (!queryParams.Opleiding && isCategoryFiltered) {
populateDropdownFromItems(
opleidingSelect,
items,
queryParams.Categorie,
'Kies een optie...'
);
}
// Handle cases where 'Categorie' query param is missing
if (!queryParams.Categorie) {
populateDropdownFromItems(categorySelect, items, null, 'Kies een optie...');
}
}
// Helper to populate dropdown from items
function populateDropdownFromItems(dropdown, items, filterValue, placeholder) {
dropdown.innerHTML = '';
dropdown.appendChild(createPlaceholder(placeholder));
items.forEach(({ element }) => {
const textValue = element.querySelector('[fs-cmsselect-element]');
if (!filterValue || textValue?.getAttribute('data-category') === filterValue) {
const optionElement = document.createElement('option');
optionElement.value =
textValue.getAttribute('data-value') || textValue.textContent.trim();
optionElement.textContent = textValue.textContent.trim();
dropdown.appendChild(optionElement);
}
});
}
// Populate fields and apply filtering on page load
const queryParams = getQueryParams();
applyCascadingFilters(queryParams);
},
]);
</script>
Thank you for sending the new script. I think we are very close now! When you click on a query parameter URL, the first and second choices are locked, which works great. However, the third choice is automatically set to the placeholder, even when the query parameter is correctly filled for the third option.
Another issue occurs when you open the page without a query parameter. The options that should be loaded for the first select field are not visible. Instead, it starts with the placeholder, and if you click on the select field, the options of the second select field are loaded into the first.
Lastly, the filtering is not working for the second and third select fields.