En un carrito de compras hecho a medida, extraigo de mi base de datos una lista de opciones que tiene un producto en particular. El número de estas opciones puede variar según el producto. Luego convierto esa lista de opciones en una matriz de JavaScript.
Un ejemplo con 3 opciones:
{"Small":{"Super":{"Pack":"parta","Case":"parte"},"Maxi":{"Pack":"partb","Case":"partf"}},"Large":{"Super":{"Pack":"partc","Case":"partg"}},"X Large":{"Maxi":{"Pack":"partd"}}}Usando lo anterior, ahora me gustaría generar un campo de selección HTML, enumerando todas las "primeras" opciones:
<select> <option value="Small">Small</option> <option value="Large">Large</option> <option value="X Large">X Large</option> </select> Una vez que el usuario ha seleccionado la primera opción, necesito otro cuadro <select> para cargar las opciones que están disponibles para su selección. Entonces, si seleccionaron "Pequeño" desde arriba, el nuevo cuadro de selección sería:
<select> <option value="Super">Super</option> <option value="Maxi">Maxi</option> </select>Finalmente, cuando seleccionan de esta lista, se carga un tercer cuadro de selección en las opciones finales, junto con los números de pieza como valores:
<select> <option value="parta">Pack</option> <option value="parte">Case</option> </select>La cantidad de opciones puede variar, de cero a 4. Sin embargo, cada vez que hay opciones disponibles, debo obtener el número de pieza según la selección del usuario. El número de pieza no tiene que ser necesariamente el valor de la última selección, se puede enviar a una nueva variable oculta.
Puedo lograr esto usando ajax, haciendo una llamada ajax cada vez que se elige una selección, pero ¿se puede hacer a través de JavaScript/jQuery, sin tener que hacer llamadas ajax, dado que la matriz está en la página y disponible para usar?
Cuando cree dinámicamente el elemento de select , también determine qué "nodo" en su estructura de árbol va con ese elemento y utilícelo para:
selectselect aún más con las opciones realesselect con la misma funciónAquí hay un código para la inspiración:
let optionTree = {"Small":{"Super":{"Pack":"parta","Case":"parte"},"Maxi":{"Pack":"partb","Case":"partf"}},"Large":{"Super":{"Pack":"partc","Case":"partg"}},"X Large":{"Maxi":{"Pack":"partd"}}}; let container = document.querySelector("#container"); addSelector(optionTree); function addSelector(node) { let select = document.createElement("select"); // Start with the default option: let option = document.createElement("option"); option.text = "Please select..."; select.add(option); for (let key in node) { // Populate the select element let option = document.createElement("option"); option.value = key; option.text = key; select.add(option); } container.appendChild(select); // Add it to the page function change() { // Remove select elements that come after the selection while (select.nextElementSibling) { select.nextElementSibling.remove(); } let key = select.value; if (node[key] && typeof node[key] !== "string") { addSelector(node[key]); // Create the next select element(s) } } // Call the above function whenever a selection is made select.addEventListener("change", change); change(); // ... and also call it now } <div id="container"></div>Suponiendo que ya tiene los tres elementos de selección en el DOM, puede completar la primera selección y agregar un detector de eventos de cambio tanto al primero como al segundo para lograrlo. Prueba esto
let $s1 = document.querySelector('#select-1'); let $s2 = document.querySelector('#select-2'); let $s3 = document.querySelector('#select-3'); let object = {"Small":{"Super":{"Pack":"parta","Case":"parte"},"Maxi":{"Pack":"partb","Case":"partf"}},"Large":{"Super":{"Pack":"partc","Case":"partg"}},"X Large":{"Maxi":{"Pack":"partd"}}}; // add options to first select $s1.innerHTML = '<option></option>'; // empty select Object.keys(object).forEach(val => $s1.append(new Option(val, val))); // append children $s1.dispatchEvent(new Event('change')); // trigger change event // listen to change event on first select/get options for second select $s1.addEventListener('change', function(e){ $s2.innerHTML = '<option></option>'; // empty select // append children Object.keys(object[e.target.value] ?? []).forEach(val => { $s2.appendChild(new Option(val, val)); }); // trigger change event $s2.dispatchEvent(new Event('change')); }); // listen to change event on second select/get options for third select $s2.addEventListener('change', function(e){ $s3.innerHTML = '<option></option>'; // empty select // append children Object.entries(object[$s1.value]?.[e.target.value] ?? []).forEach(([key, val]) => { $s3.appendChild(new Option(key, val)); }); }); select {min-width:80px} <select id="select-1"></select> <select id="select-2"></select> <select id="select-3"></select>