Tengo un MutationObserver que observa un elemento con id shipping_cost y activa la función updateTotal() cuando cambia el HTML interno del elemento. El MutationObserver funciona cuando el HTML interno se cambia desde una fuente externa (como el elemento de inspección). Pero cuando cambio el HTML interno desde el interior de javascript, MutationObserver no fue despedido, ¿dónde hice mal?
Se puede ver en el código que al final de javascript, traté de cambiar el HTML interno desde el interior de javascript, pero el HTML interno del elemento con id total no cambió, lo que indica que updateTotal() no se activó.
Sin embargo, la función updateTotal() se activa cuando cambio el HTML interno usando el elemento de inspección (en Chrome: clic derecho -> inspeccionar). Cómo puedo solucionar esto ?
const subtotal = document.getElementById("subtotal"); const shipping_cost = document.getElementById("shipping_cost"); const total = document.getElementById("total"); const price_loading_text = "Loading . . ."; shipping_cost.innerHTML = price_loading_text; total.innerHTML = price_loading_text; function updateTotal() { if(shipping_cost.innerHTML != price_loading_text) { total.innerHTML = parseFloat(subtotal.innerHTML) + parseInt(shipping_cost.innerHTML); } else { total.innerHTML = price_loading_text; } } updateTotal(); observer = new MutationObserver(updateTotal); observer.observe(shipping_cost, { attributes: false, childList: false, subtree: true, characterData: true}); shipping_cost.innerHTML = "100"; <p>Subtotal: <span id="subtotal" class="subtotal">9999</span></p> <p>Shipping_cost: <span id="shipping_cost" class="shipping_cost"></span></p> <p>Total: <span id="total" class="total"></span></p>Haciendo
shipping_cost.innerHTML = "100";modifica los elementos secundarios del elemento; específicamente, elimina todos sus elementos secundarios existentes del DOM y luego inserta un nuevo nodo de texto como elemento secundario. Eso debería hacer que sea intuitivo que no necesita
childList: false,pero en lugar
childList: true,para que se vean los cambios en los niños.
const subtotal = document.getElementById("subtotal"); const shipping_cost = document.getElementById("shipping_cost"); const total = document.getElementById("total"); const price_loading_text = "Loading . . ."; shipping_cost.innerHTML = price_loading_text; total.innerHTML = price_loading_text; function updateTotal() { if (shipping_cost.innerHTML != price_loading_text) { total.innerHTML = parseFloat(subtotal.innerHTML) + parseInt(shipping_cost.innerHTML); } else { total.innerHTML = price_loading_text; } } updateTotal(); observer = new MutationObserver(updateTotal); observer.observe(shipping_cost, { attributes: false, childList: true, subtree: true, characterData: true }); shipping_cost.innerHTML = "100"; <p>Subtotal: <span id="subtotal" class="subtotal">9999</span></p> <p>Shipping_cost: <span id="shipping_cost" class="shipping_cost"></span></p> <p>Total: <span id="total" class="total"></span></p>Dicho esto, recomendaría usar solo un observador cuando el código sobre el que no tiene control hace una mutación en el DOM. Si tiene control sobre todo el código de la aplicación, generalmente es mucho más fácil simplemente llamar a la función deseada después de cambiar el DOM. Por ejemplo, no hagas
shipping_cost.innerHTML = "100";pero hazlo
const updateShippingCost = (newCost) => { shipping_cost.innerHTML = newCost; total.innerHTML = Number(subtotal.innerHTML) + newCost; }; updateShippingCost(100);