Hi all. I’m wondering if anyone can help me get unstuck. I’m using CMS Filters and trying to use the api to create a more complex use case.
I’m building a product configurator but there is a ton of logic. I’ve written everything as modular as I can, but I’m running into issues where I need to clear categories of filters using the api, but can’t can’t figure out how to do that without it being inside renderitems. Therefore, it’s creating an infinte loop. I’ve tried to use fs-cmsfilter-clear and it works but only for one or two categories before overlapping.
Here is my read only link.
the published site (which won’t work without the code below).
here is my code.
const FilterHelper = {
disableOptions(optionIds) {
optionIds.forEach(id => {
const element = $(`#${id}`);
console.log(`Disabling element: ${id}`); // Debug line
element.parent().addClass('is-disabled');
element.parent().removeClass('is-active');
element.prop('disabled', true);
});
},
enableAndClickOptions(optionIds) {
optionIds.forEach(id => {
const element = $(`#${id}`);
console.log(`Enabling and clicking element: ${id}`); // Debug line
element.parent().removeClass('is-disabled');
element.prop('disabled', false);
element.click();
});
},
enableOptions(optionIds) {
optionIds.forEach(id => {
const element = $(`#${id}`);
console.log(`Enabling element: ${id}`); // Debug line
element.parent().removeClass('is-disabled');
element.prop('disabled', false);
});
},
containsOption(selectedOptions, optionName) {
return selectedOptions.some(set => Array.from(set).some(option => option.includes(optionName)));
},
applyRules(filterInstance, selectedOptions, rules) {
// Loop through all rules
Object.entries(rules).forEach(([ruleKey, ruleValue]) => {
// Check if the selected options contain the rule key
if (this.containsOption(selectedOptions, ruleKey)) {
// If the rule key is in the selected options, hide, enable, and show/click options as defined by the rule
this.disableOptions(ruleValue.disable);
this.enableOptions(ruleValue.enable);
this.enableAndClickOptions(ruleValue.showAndClick);
}
});
}
};
const rules = {
'Wall Switch': {
showAndClick: [],
disable: ['Adjustable'],
enable: ['High', 'Non-Dimming','Night-Light', 'Anti-Fog', '5000', '4000', '3000', '3500','2700', 'Standard', 'ELV-Dimmable', '0-10-Dimmable'],
resetKey: ['color temperature'],
},
'Touch Sensor': {
showAndClick: [],
disable: ['Adjustable', 'Night-Light'],
enable: ['High', 'Non-Dimming', 'Anti-Fog', '5000', '4000', '3000', '3500','2700', 'Standard', 'ELV-Dimmable', '0-10-Dimmable'],
resetKey: ['color temperature'],
},
'Matrix Touch System': {
showAndClick: ['Adjustable', 'High', 'Non-Dimming'],
disable: ['Night-Light', 'Anti-Fog', '5000', '4000', '3000', '3500','2700', 'Standard', 'ELV-Dimmable', '0-10-Dimmable'],
enable: [],
},
'Thin Frame': {
showAndClick: [],
disable: ['Full-Frame-Edge', 'Double-Long-Side-Edge', 'Double-Short-Side-Edge', 'Single-Long-Side-Edge', 'Single-Short-Side-Edge'],
enable: [],
resetKey: [],
},
'Wide Frame': {
showAndClick: [],
disable: [],
enable: ['Full-Frame-Edge', 'Double-Long-Side-Edge', 'Double-Short-Side-Edge', 'Single-Long-Side-Edge', 'Single-Short-Side-Edge'],
resetKey: [],
},
'Inset': {
showAndClick: [],
disable: ['Indirect'],
enable: ['Direct', 'Both-Direct-And-Indirect'],
resetKey: [],
},
'Edge': {
showAndClick: [],
disable: ['Night Light', 'Both-Direct-And-Indirect'],
enable: ['Direct', 'Indirect'],
resetKey: [],
},
'No Frost': {
showAndClick: ['Indirect'],
disable: ['Direct', 'Both-Direct-And-Indirect', 'Night-Light', 'Anti-Fog'],
enable: [],
resetKey: [],
},
'Round': {
showAndClick: ['Indirect', 'Vertical Mounting'],
disable: ['Night Light', 'Direct', 'Both-Direct-And-Indirect'],
enable: [],
resetKey: [],
},
'Adjustable': {
showAndClick: ['High', 'Non-Dimming'],
disable: ['ELV-Dimmable', '0-10-Dimmable'],
enable: [],
resetKey: [],
}
};
window.fsAttributes = window.fsAttributes || [];
window.fsAttributes.push([
'cmsfilter',
(filterInstances) => {
console.log('cmsfilter Successfully loaded!');
console.log('Filter Instances:', filterInstances);
filterInstances.forEach((filterInstance) => {
filterInstance.listInstance.on('renderitems', () => {
const selectedOptions = [];
filterInstance.filtersData.forEach((filterData) => {
// Existing logic to manage selected options
const selectedOption = document.querySelector(`.selected-option[filter-target="${filterData.filterKeys[0]}"]`);
if (selectedOption) {
if (filterData.values.size > 0) { // Check if the filter is active
// Get the selected values
let selectedValues = Array.from(filterData.values).join(',');
// Add a prefix to the selected values based on the filter key
selectedValues = filterData.filterKeys[0] === 'width' ? `W: ${selectedValues}` : filterData.filterKeys[0] === 'height' ? `H: ${selectedValues}` : selectedValues;
// Add a suffix to the selected values based on the filter key
selectedValues += filterData.filterKeys[0] === 'diameter' ? '" in diameter' : '';
// Update the text content of the selected-option element
selectedOption.textContent = selectedValues;
// Change the display property of the selected-option element to block
selectedOption.style.display = 'block';
} else {
// If the filter is not active, set the textContent of the selected-option element to an empty string and hide it
selectedOption.textContent = '';
selectedOption.style.display = 'none';
}
} else {
console.log(`No selected-option element found for filter key: ${filterData.filterKeys[0]}`);
}
// Then proceed with new rule application logic
selectedOptions.push(filterData.values);
});
// Apply the rules
FilterHelper.applyRules(filterInstance, selectedOptions, rules);
});
});
},
]);```
Thank you for any insight. If there is a better way to accomplish what I'm after please feel free to provide feedback.