2009-03-01 14 views
35

Ho un modulo HTML con oltre 20 campi. Ho anche un paio di link nella pagina che porteranno l'utente lontano dal modulo ... potenzialmente senza aver salvato alcuna modifica.Qual è il modo più semplice per rilevare se almeno un campo è stato modificato su un modulo HTML?

Voglio avvisare (JS conferma) l'utente onClick di questi collegamenti se uno dei campi modulo è cambiato, ma non voglio creare un'enorme istruzione switch che devo quindi mantenere man mano che aggiungo nuovi campi alla forma. So come creare una lunga lista di istruzioni "if" in Javascript, nominando ciascuno dei campi e verificando ciascun valore, ma non voglio farlo se riesco a farla franca.

Qual è il modo più semplice per verificare se l'utente ha modificato almeno uno dei valori del campo?

risposta

7

Utilizzare jQuery è molto semplice. Dovresti essere in grado di usare la stessa premessa per ottenere lo stesso risultato anche in vanilla JavaScript.

var $inps = $('#myForm').find('input,select,textarea') 
    , formAltered = false 
; 
$inps.change(function() { 
    formAltered = true; 
    $inps.unbind('change'); // saves this function running every time. 
}); 

L'unico problema è se si cambia un valore, e poi cambiare di nuovo al originale, sarà ancora segnalare il modulo come modificata.

+0

+1, è possibile elaborare questa per eliminare il caso di dati in realtà non cambiano - è possibile salvare lo stato iniziale e confrontarlo ad esso (evento onfocus uso per questo) e solo allora impostare il modulo per "sporco" – Dror

+0

Puoi rendere la prima linea migliore: 'var $ inps = $ ('# myForm: input'), formAltered = false;' – ANeves

68

Approach

  1. serializzare la forma (e tutti i suoi valori) prima di visualizzarlo (jQuery way, Prototype way)
  2. serializzare nuovamente in un gestore "onbeforeunload" evento

Se i due non corrispondono, quindi devono aver cambiato il modulo, quindi restituire una stringa (ad es. "Hai dati non salvati") dal tuo gestore onbeforeunload.

Questo metodo consente ai campi modulo di evolvere mentre la logica "conferma se cambia" rimane la stessa.

Esempio(misto javascript e jquery)

var form_clean; 

// serialize clean form 
$(function() { 
    form_clean = $("form").serialize(); 
}); 

// compare clean and dirty form before leaving 
window.onbeforeunload = function (e) { 
    var form_dirty = $("form").serialize(); 
    if(form_clean != form_dirty) { 
     return 'There is unsaved form data.'; 
    } 
}; 
+0

Ooo, questa è un'idea davvero dolce. Bello. –

+10

Nel 2014, questa è ancora la migliore pratica? –

+0

C'è un motivo per cui la prima linea non è solo 'var form_clean = $ (" form "). Serialize();'? – Edd

5

Ecco un uno di linea che è possibile aggiungere ai moduli:

$(':input',document.myForm).bind("change", function() { 
    enablePrompt(true); }); // Prevent accidental navigation away 

E allora si può fare l'enableUnloadPrompt () per l'intero sito:

function enablePrompt(enabled) { 
    window.onbeforeunload = enabled ? "Your changes are not saved!" : null; 
} 

E, infine, prima di inoltrare il modulo correttamente, assicurarsi di:

enablePrompt(false); 

Questo non controllerà per vedere se la forma è diversa nei valori, solo se il modulo è stato mai modificato dall'utente. Ma è semplice e facile da usare.

3

Questo potrebbe essere gestito con una sola variabile booleana, la chiamiamo gestione di bit dirty. Se hai osservato, generalmente nelle pagine web, una volta che l'utente esegue un'azione di modifica su uno qualsiasi dei campi, il modulo è considerato sporco (modificato) (anche se i dati rimangono invariati dopo la modifica). Quando l'utente tenta di allontanarsi dalla pagina, viene richiesto all'utente se desidera salvare le modifiche.

Come per la pratica standard, non vi è alcun controllo se dopo aver modificato un campo se il valore effettivamente è stato modificato o meno. Ad esempio: se l'utente modifica e appende 'xyz' a un campo di testo e poi elimina 'xyz' essenzialmente i dati del modulo rimangono gli stessi di prima, ma il modulo è ancora considerato come 'sporco' e all'utente viene richiesto un messaggio di avviso quando cerca di allontanarsi.

Quindi, se si desidera implementare queste cose diventa piuttosto semplice. Dovresti semplicemente aggiungere eventcinder onchange() ai controlli e impostare la variabile booleana globale come isDirty su true all'interno di quegli eventhandler.

Una volta che l'utente vuole allontanarsi, è possibile visualizzare un messaggio "Ci possono essere modifiche non salvate nella pagina corrente. Vuoi salvarle?". L'utente non sarà deluso anche se si accorge che la sua modifica non ha modificato i dati iniziali.

Le risposte fornite in precedenza implementano questo stesso comportamento. E ho scritto questo perché sembravi avere un'idea per controllare ogni singolo campo con il suo valore iniziale per vedere se era veramente alterato dopo la modifica. Volevo solo dirti che controllare ogni campo non è affatto necessario.

11

Sono abbastanza sicuro che questa sia una cattiva idea, ma volevo buttarla lì.

I campi modulo hanno un modo per ottenere il "valore predefinito" (ovvero il valore che il campo aveva quando è stato caricato) e lo si può confrontare con il valore corrente. Un semplice ciclo su tutti i campi rimuove la necessità di manutenzione se si aggiungono campi al modulo.

Ci possono essere o meno vari bug del browser associati alle proprietà "valore predefinito", quindi non mi fiderei di questo metodo senza test approfonditi. Il codice sotto è una prova di concetto, e non è usato (da me) in nessuna applicazione reale.

function IsDirty(form) { 
    for (var i=0; i<form.elements.length; i++) { 
     var field = form.elements[i]; 
     switch (field.type) { 
      case "select-multiple": 
      case "select-one": 
       var options = field.options; 
       for (var j=0; j<options.length; j++) { 
        if(options[j].selected != options[j].defaultSelected) return true; 
       } 
       break; 
      case "text": 
      case "file": 
      case "password": 
       if (field.value != field.defaultValue) return true; 
       break; 
      case "checkbox": 
      case "radio": 
       if (field.checked != field.defaultChecked) return true; 
       break; 
     } 
    } 
    return false; 
} 
+0

Per quanto ne so questo è l'unico modo per farlo. Previene i problemi con, ad esempio Firefox, mantenendo i nuovi valori del modulo dopo un aggiornamento. –

Problemi correlati