Estoy escribiendo un script de usuario que debe responder al cambio de valor de un elemento <input> , sin importar cómo se haya realizado el cambio.
Para las interacciones del usuario, esto es fácil: solo agregue un oyente para el evento de input . Sin embargo, todavía no he encontrado una manera de responder al valor de la entrada que se establece directamente cambiando su propiedad .value .
Intenté agregar oyentes para los eventos de change y input (ninguno se activa) y agregué un MutationObserver tanto para los atributos de la entrada como para la lista de elementos secundarios de los padres de la entrada (nuevamente, ninguno se activa). Tampoco parece haber un descriptor de propiedad que pueda modificar.
¿Cómo puedo activar el código para que se ejecute cuando se establece la propiedad .value de un elemento <input> ?
<!DOCTYPE html> <html> <head> <title>Detect value change</title> <script type="module"> const range = document.querySelector('input'); range.addEventListener('change', (event) => console.log('Change:', event)); range.addEventListener('input', (event) => console.log('Input:', event)); const observer = new MutationObserver((mutations) => console.log('Mutation:', mutations)); observer.observe(range, { attributes: true, attributeFilter: ['value'] }); observer.observe(range.parentNode, { childList: true }); console.log('Property descriptors:', Object.getOwnPropertyDescriptors(range)); // Somewhere else, in code I don't control: document.querySelector('input').value = 7; </script> </head> <body> <input type="range" min="0" max="10" /> </body> </html>Salida de la consola:
Property descriptors: {}Activa el evento de cambio después de actualizar el valor mediante programación:
range.value = 7; var event = new Event('change'); range.dispatchEvent(event);Consulte esta respuesta para obtener gran información sobre por qué MutationObserver no detecta modificaciones en las propiedades.
Si no puede modificar la forma en que se cambia el valor ( node.setAttribute('value', 'newValue') su MutationObserver , por ejemplo), entonces creo que su única opción es, lamentablemente, un setInterval que se aplica a los cambios de valor a una frecuencia establecida.
Algo como esto:
const range = document.querySelector('input'); document.getElementById('incrementValue').addEventListener('click', () => { const val = range.valueAsNumber; range.value = range.value === range.max ? range.min : String(val + 1); }); let currentVal; setInterval(() => { // Check for val changes every 1sec if (range.value === currentVal) { return; } currentVal = range.value; console.log(`New value detected. New value is ${range.value}`); }, 1000); <!DOCTYPE html> <html> <head> <title>Detect value change</title> </head> <body> <button id="incrementValue">Increment value</button> <input type="range" min="0" max="10" value="0" /> </body> </html>