Hello everyone,
When placed on a category archive, I would like the “Filter - Checkbox” element to only display subcategories of the archive category. Does anyone know how to achieve this?
Cheers.
Hello everyone,
When placed on a category archive, I would like the “Filter - Checkbox” element to only display subcategories of the archive category. Does anyone know how to achieve this?
Cheers.
I think this works like this.
What I am missing is collapsible subcategories list inside a hierarchical checkbox filter element.
I set up the checkbox filter element to show my categories and subcategories. Is is a total mess, is there any workaround to make the subcategories collapsible. Just a small section of my filter, it describes the problem very well:
@timmse Can you recommend anything to make the filter usable for the customers? Thank you!
Hi @Andris ,
It’s not available in Bricks query filters currently.
Someone sent us via email something similar to this
We already recorded it into our improvement task.
Hello @itchycode
I implemented a JS fix for this problem as a temporary solution. I hope you can upgrade Bricks to work more seamlessly with WooCommerce ![]()
My fix is this with an extra Code element – needs some improvement but not bad. (Or course it would be far better if the DOM elements would be initially in a hierarchy and there would be no need for JS trickery, but for now this works.)
JS:
(function () {
const INIT_ATTR = 'data-tree-init';
const openStates = new Set(); // stored by value attribute
function saveState() {
const list = document.querySelector('.brxe-filter-checkbox');
if (!list) return;
openStates.clear();
list.querySelectorAll('li.is-open').forEach(li => {
const input = li.querySelector('input[type="checkbox"]');
if (input) openStates.add(input.value);
});
}
function restoreState() {
const list = document.querySelector('.brxe-filter-checkbox');
if (!list) return;
list.querySelectorAll('li').forEach(li => {
const input = li.querySelector('input[type="checkbox"]');
if (input && openStates.has(input.value)) {
li.classList.add('is-open');
}
});
}
function init() {
const list = document.querySelector('.brxe-filter-checkbox');
if (!list) return;
const items = [...list.querySelectorAll(`li:not([${INIT_ATTR}])`)];
if (items.length === 0) return;
for (let i = items.length - 1; i >= 0; i--) {
const li = items[i];
const depth = parseInt(li.dataset.depth);
const children = [];
let next = li.nextElementSibling;
while (next && parseInt(next.dataset.depth) > depth) {
if (parseInt(next.dataset.depth) === depth + 1) children.push(next);
next = next.nextElementSibling;
}
li.setAttribute(INIT_ATTR, '1');
if (children.length === 0) continue;
const wrapper = document.createElement('div');
wrapper.className = 'children-wrapper';
const ul = document.createElement('ul');
wrapper.appendChild(ul);
next = li.nextElementSibling;
while (next && parseInt(next.dataset.depth) > depth) {
const toMove = next;
next = next.nextElementSibling;
ul.appendChild(toMove);
}
li.appendChild(wrapper);
const icon = document.createElement('span');
icon.className = 'toggle-icon';
icon.setAttribute('aria-hidden', 'true');
icon.innerHTML = `<!-- @license lucide-static v0.546.0 - ISC -->
<svg
class="lucide lucide-chevron-down"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m6 9 6 6 6-6" />
</svg>`;
li.querySelector('label').appendChild(icon);
li.querySelector('label').addEventListener('click', (e) => {
if (e.target.tagName === 'INPUT') return;
e.preventDefault();
li.classList.toggle('is-open');
// Azonnal mentjük a kattintás után
saveState();
});
}
// Basic state: if there is only one top level element and there is no saved state
const topLevel = list.querySelectorAll(':scope > li[data-depth="0"]');
if (topLevel.length === 1 && openStates.size === 0) {
topLevel[0].classList.add('is-open');
saveState();
}
// Restore saved state
restoreState();
}
init();
const observer = new MutationObserver((mutations) => {
const relevant = mutations.some(m =>
[...m.addedNodes].some(n => n.nodeType === 1 && (
n.matches?.('li') || n.querySelector?.('li')
))
);
if (relevant) init();
});
const target = document.querySelector('.brxe-filter-checkbox') ?? document.body;
observer.observe(target, { childList: true, subtree: true });
})();
CSS:
/* Wrapper minden li köré kell egy animálható konténer */
.brxe-filter-checkbox {
gap: 8px;
display: flex;
flex-direction: column;
}
.brxe-filter-checkbox li .children-wrapper {
display: grid;
grid-template-rows: 0fr;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
overflow: hidden;
}
.brxe-filter-checkbox li.is-open > .children-wrapper {
grid-template-rows: 1fr;
margin-top: 8px;
}
.brxe-filter-checkbox li .children-wrapper > ul {
min-height: 0;
list-style: none;
padding: 0;
gap: 8px;
display: flex;
flex-direction: column;
}
.brx-option-disabled {
opacity: 1;
pointer-events: auto;
}
.brx-option-text {
text-wrap: nowrap
}
.toggle-icon {
display: inline-flex;
align-items: center;
margin-left: auto;
vertical-align: middle;
}
.toggle-icon svg {
transition: all 0.3s ease;
transform: rotate(0deg);
width: 18px;
height: 18px;
stroke: var(--gray-300);
}
.toggle-icon:hover svg {
stroke: var(--gray-500);
}
.is-open > label .toggle-icon svg {
transform: rotateX(180deg);
stroke: var(--gray-500);
}