Detección de modificaciones en elementos de un formulario con JavaScript

En el desarrollo de aplicaciones web, es una práctica común verificar si el usuario ha realizado cambios en un formulario antes de permitir que navegue a otra sección o para habilitar el botón de guardado. A continuación, se presenta una implementación técnica para rastrear el estado inicial de los elementos y determinar si han sido alterados.

La lógica se basa en capturar el valor original de cada campo (input, select, textarea) y almacenarlo temporalmente en el objeto del DOM para realizar comparaciones posteriores.


/**
 * Inicializa el estado original de todos los elementos del formulario.
 * Se recomienda llamar a esta función al cargar la página o tras guardar los datos.
 */
function registrarEstadoInicial(formulario) {
    const elementos = formulario.elements;
    for (let i = 0; i < elementos.length; i++) {
        const campo = elementos[i];
        
        // Ignorar botones y elementos de envío
        if (campo.type === 'submit' || campo.type === 'reset' || campo.type === 'button') continue;

        // Almacenar el valor inicial según el tipo de campo
        if (campo.type === 'checkbox' || campo.type === 'radio') {
            campo.dataset.valorOriginal = campo.checked;
        } else {
            campo.dataset.valorOriginal = campo.value;
        }
    }
}

/**
 * Compara el estado actual con el estado almacenado.
 * @return {boolean} True si hay cambios, False si el formulario está íntegro.
 */
function verificarCambios(formulario) {
    const elementos = formulario.elements;
    for (let i = 0; i < elementos.length; i++) {
        const campo = elementos[i];
        
        if (campo.dataset.valorOriginal === undefined) continue;

        let valorActual;
        if (campo.type === 'checkbox' || campo.type === 'radio') {
            valorActual = campo.checked;
        } else {
            valorActual = campo.value;
        }

        // Se compara como String para evitar discrepancias de tipos
        if (String(valorActual) !== String(campo.dataset.valorOriginal)) {
            return true;
        }
    }
    return false;
}

/**
 * Función controladora para la acción de envío
 */
function procesarFormulario(e, formulario) {
    if (verificarCambios(formulario)) {
        alert("Se han detectado modificaciones en los datos.");
    } else {
        alert("No se ha realizado ningún cambio.");
    }
    return false; // Evita el envío real para propósitos de prueba
}

Para implementar esta solución en un documento HTML, se debe asegurar que la función de inicialización se ejecute una vez que el DOM esté listo, y vincular la comprobación al evento onsubmit.


<form id="miFormulario" onsubmit="return procesarFormulario(event, this)">
    <div>
        <label>Nombre:</label>
        <input type="text" name="nombre" value="Usuario Demo">
    </div>

    <div>
        <label>Opciones:</label>
        <input type="radio" name="opcion" value="1"> A
        <input type="radio" name="opcion" value="2" checked> B
    </div>

    <div>
        <label>Intereses:</label>
        <input type="checkbox" name="interes" checked> Suscribirse
    </div>

    <div>
        <label>País:</label>
        <select name="pais">
            <option value="es">España</option>
            <option value="mx" selected>México</option>
            <option value="ar">Argentina</option>
        </select>
    </div>

    <div>
        <textarea>Texto inicial del área.</textarea>
    </div>

    <hr>
    <input type="submit" value="Validar cambios">
    <input type="reset" value="Restablecer">
</form>

<script>
    // Captura el estado inicial al cargar la ventana
    window.onload = function() {
        const form = document.getElementById('miFormulario');
        registrarEstadoInicial(form);
    };
</script>

Este enfoque es eficiente porque utiliza la propiedad dataset de HTML5 para mantener el estado sin necesidad de variables globales adicionales. Además, maneja correctamente el escenario donde un usuario modifica un campo y luego lo devuelve a su valor original, indicando en ese caso que no existan cambios pendientes.

Etiquetas: JavaScript html-forms DOM web-development frontend

Publicado el 6-6 00:04