Tengo un cuadro de selección que funciona como pestañas, funciona bien siempre que hay una sección. Sin embargo, quiero que funcione para múltiples secciones, básicamente quiero que sea único y funcione por sí solo. No puedo agregar una clase personalizada para un elemento diferente en html porque se agrega dinámicamente a través del sistema html y todos tienen las mismas clases. ¿Hay alguna forma de evitar esto usando javascript?
const selectList = document.querySelectorAll("select"); for (let i = 0; i < selectList.length; i++) { selectList[i].addEventListener("change", toggle); } function toggle(e) { e.target.closest(".section").querySelectorAll(".ul-data").forEach((el) => { el.hidden = el.dataset["name"] !== e.target.value; }); } <select class="dropdown"> <option value="test">Test</option> <option value="test1">Test1</option> </select> <div class="section section-1"> <ul class="ul-data" data-name="test"> <li>Item</li> </ul> </div> <select class="dropdown"> <option value="test">Test</option> <option value="test1">Test1</option> </select> <div class="section section-2"> <ul class="ul-data" data-name="test"> <li>Item</li> </ul> </div>Como puede ver en el fragmento, cuando cambia el valor de la primera sección, la otra sección también cambia, lo que no quiero que suceda.
Debe dirigirse a los padres cuya clase comienza con ^= "section-" .
Entonces, al seleccionar sus elementos, asegúrese de que no se consulten desde el document sino desde su sección principal: Elemento N
const EL = (sel, el) => (el || document).querySelector(sel); const ELS = (sel, el) => (el || document).querySelectorAll(sel); const ELS_section = ELS('[class^="section-"], [class*=" section-"]'); // PS: use rather a common ".section" in HTML ELS_section.forEach(EL_section => { const ELS_select = EL(".dropdown", EL_section); // descendant of EL_section const ELS_ul = ELS(".ul-data", EL_section); // descendants of EL_section ELS_select.addEventListener("change", () => { const name = ELS_select.value; ELS_ul.forEach(EL_ul => { EL_ul.hidden = name && EL_ul.dataset.name !== name; }); }); }); <div class="section-1"> <select class="dropdown"> <option value="">-- All --</option> <option value="test">Test</option> <option value="test1">Test1</option> </select> <ul class="ul-data" data-name="test"> <li>Test</li> </ul> <ul class="ul-data" data-name="test1"> <li>Test1</li> </ul> </div> <div class="section-2"> <select class="dropdown"> <option value="">-- All --</option> <option value="test">Test</option> <option value="test1">Test1</option> </select> <ul class="ul-data" data-name="test"> <li>Test</li> </ul> <ul class="ul-data" data-name="test1"> <li>Test1</li> </ul> </div>Podría usar nextElementSibling para encontrar el elemento que viene directamente después de e.target (el cuadro de selección). Sin embargo, recomiendo editar la estructura html para que haya un contenedor alrededor de los elementos select y ul para evitar que el código se rompa cuando cambie el html para que haya un elemento en el medio.
Podría escribir su propia función similar a la más cercana pero también para los hermanos.
const selectList = document.querySelectorAll("select"); for (let i = 0; i < selectList.length; i++) { selectList[i].addEventListener("change", toggle); } function toggle(e) { e.target.nextElementSibling.querySelectorAll(".ul-data").forEach((el) => { el.hidden = el.dataset["name"] !== e.target.value; }); } <select class="dropdown"> <option value="test">Test</option> <option value="test1">Test1</option> </select> <div class="section section-1"> <ul class="ul-data" data-name="test"> <li>Item</li> </ul> </div> <select class="dropdown"> <option value="test">Test</option> <option value="test1">Test1</option> </select> <div class="section section-2"> <ul class="ul-data" data-name="test"> <li>Item</li> </ul> </div>prueba esto:
const selectList = document.querySelectorAll("select"); for (let i = 0; i < selectList.length; i++) { selectList[i].addEventListener("change", toggle); } function toggle(e) { let parent = e.target.closest("[class^='section-']"); if(!parent) return; let ulList = parent.querySelectorAll(".ul-data"); for (let i = 0; i < ulList.length; i++) { ulList[i].hidden = ulList[i].dataset["name"] !== e.target.value; } } <div class="section-1"> <select class="dropdown"> <option value="test">Test</option> <option value="test1">Test1</option> </select> <ul class="ul-data" data-name="test"> <li>Item</li> </ul> <ul class="ul-data" data-name="test1"> <li>Item2</li> </ul> </div> <div class="section-2"> <select class="dropdown"> <option value="test">Test</option> <option value="test1">Test1</option> </select> <ul class="ul-data" data-name="test"> <li>Item</li> </ul> <ul class="ul-data" data-name="test1"> <li>Item2</li> </ul> </div>