Topic: Nested accordion trigger event show and hide to its parents
Alan Schwertner
free
asked 2 weeks ago
Expected behavior
The event should be triggered only in the target collapse component, not in its parent elements.
Actual behavior
All *.mdb.collapse events (show, hide, shown, and hidden) are propagated up the DOM, even if no data-mdb-target is defined.
Resources (screenshots, code snippets etc.)
https://jsfiddle.net/8fj74mpu/25/
// Even when filtering by the event target, the invoked event cannot be isolated to the correct accordion; it always propagates up the DOM.
$('.accordion-collapse').on('show.mdb.collapse', function (e) {
if (e.target === this) {
console.log('show: ', $(e.currentTarget).attr('id'));
}
});
DOM:
<!-- Nested accordion example -->
<div class="accordion" id="level_1">
<div class="accordion-item">
<h2 class="accordion-header" id="level_1_menu_1">
<button
data-mdb-collapse-init
class="accordion-button collapsed"
type="button"
data-mdb-target="#level_1_collapse_1"
>
Menu #1
</button>
</h2>
<div id="level_1_collapse_1" class="accordion-collapse collapse">
<div class="accordion-body">
<!-- Nest another accordion -->
<div class="accordion" id="level_2">
<div class="accordion-item">
<h2 class="accordion-header" id="level_2_menu_1">
<button
data-mdb-collapse-init
class="accordion-button collapsed"
type="button"
data-mdb-target="#level_2_collapse_1"
>
Submenu #1.1
</button>
</h2>
<div id="level_2_collapse_1" class="accordion-collapse collapse">
<div class="accordion-body">Content 1.1</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Kamila Pieńkowska
staff
answered 1 week ago
You may consider using existing treeview plugin: https://mdbootstrap.com/docs/standard/plugins/tree-view/
Alan Schwertner
free
answered 1 week ago
Thank you, Kamila.
I'm working on a multilevel tree menu, and I need to monitor both show
and hide
events because a menu can be opened or closed dynamically, even without a click. For example, an action like "reveal in menu" might need to open one accordion and close others.
I've reviewed the source code but haven't been able to figure out how the event-handler.js
works internally.
Temporarily, I'm using this (not very elegant) solution, but it achieves the desired result since events on parent elements are propagated almost simultaneously:
const isolateCollapseEvent = {
target: null,
time: null,
setTarget(target) {
// Keep the first target
if (!this.time || Date.now() - this.time > 50) {
this.target = target;
this.time = Date.now();
}
},
getTarget() {
return this.target;
}
};
$('#tree-menu .accordion-collapse').on('show.mdb.collapse', (e) => {
// Keep the first target because all events are captured almost simultaneously
isolateCollapseEvent.setTarget(e.currentTarget);
// Filter other targets
if (isolateCollapseEvent.getTarget() !== e.currentTarget) {
return;
}
// Perform the task
});
Kamila Pieńkowska
staff
answered 2 weeks ago
Use this as your listener:
document.querySelectorAll('.accordion-button').forEach((btn) => {
btn.addEventListener(
'click',
(e) => {
console.log('capture click on:', e.currentTarget.dataset.mdbTarget);
},
true
);
});
FREE CONSULTATION
Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.
Answered
- ForumUser: Free
- Premium support: No
- Technology: MDB Standard
- MDB Version: MDB5 9.1.0
- Device: all
- Browser: all
- OS: all
- Provided sample code: No
- Provided link: Yes