113 votes

Moyen générique de détecter si un formulaire html est édité

J'ai un formulaire html à onglets. Lorsque l'on passe d'un onglet à l'autre, les données de l'onglet en cours sont conservées (dans la base de données) même si elles ne sont pas modifiées.

Je voudrais que l'appel de persistance ne soit effectué que si le formulaire est modifié. Le formulaire peut contenir n'importe quel type de contrôle. L'édition du formulaire ne doit pas nécessairement se faire en tapant du texte, mais en choisissant une date dans un contrôle de calendrier.

Une façon d'y parvenir serait d'afficher le formulaire en mode lecture seule par défaut et de disposer d'un bouton "Modifier". Si l'utilisateur clique sur ce bouton, l'appel à la base de données est effectué (une fois de plus, indépendamment de la modification des données). C'est une meilleure amélioration par rapport à ce qui existe actuellement).

J'aimerais savoir comment écrire une fonction javascript générique qui vérifierait si l'une des valeurs des contrôles a été modifiée ?

0 votes

Un site solution intéressante a été publié par Craig Buckler sur SitePoint. Il est particulièrement intéressant de noter que la solution ne repose pas sur jQuery et qu'elle est compatible avec tous les navigateurs.

186voto

Philippe Leybaert Points 62715

En javascript pur, ce ne serait pas une tâche facile, mais jQuery la rend très facile à réaliser :

$("#myform :input").change(function() {
   $("#myform").data("changed",true);
});

Ensuite, avant de sauvegarder, vous pouvez vérifier s'il a été modifié :

if ($("#myform").data("changed")) {
   // submit the form
}

Dans l'exemple ci-dessus, le formulaire a un id égal à "myform".

Si vous en avez besoin sous plusieurs formes, vous pouvez facilement en faire un plugin :

$.fn.extend({
 trackChanges: function() {
   $(":input",this).change(function() {
      $(this.form).data("changed", true);
   });
 }
 ,
 isChanged: function() { 
   return this.data("changed"); 
 }
});

Alors vous pouvez simplement dire :

$("#myform").trackChanges();

et vérifier si un formulaire a été modifié :

if ($("#myform").isChanged()) {
   // ...
}

18 votes

C'est simple et agréable. Cependant, si un utilisateur modifie une entrée de formulaire et revient ensuite sur cette modification (par exemple en cliquant deux fois sur une case à cocher), le formulaire sera considéré comme modifié. Le fait que cela soit acceptable ou non dépend bien sûr du contexte. Pour une alternative, voir stackoverflow.com/questions/10311663/

1 votes

Pour les entrées en direct, quelques changements sont nécessaires trackChanges: function () { $(document).on('change', $(this).find(':input'), function (e) { var el = $(e.target); $(el).closest('form').data("changed", true); });

0 votes

Merci Mate. Tu as sauvé ma journée.

42voto

mecograph Points 484

Je ne suis pas sûr d'avoir bien compris votre question, mais qu'en est-il de addEventListener ? Si vous ne vous souciez pas trop de la prise en charge d'IE8, cela devrait aller. Le code suivant fonctionne pour moi :

var form = document.getElementById("myForm");

form.addEventListener("input", function () {
    console.log("Form has changed!");
});

41voto

Matthew Vines Points 14425

Au cas où JQuery ne serait pas envisageable. Une recherche rapide sur Google a permis de trouver des implémentations Javascript des algorithmes de hachage MD5 et SHA1. Si vous le souhaitez, vous pouvez concaténer toutes les entrées de formulaire et les hacher, puis stocker cette valeur en mémoire. Lorsque l'utilisateur a terminé. Concaténer toutes les valeurs et les hacher à nouveau. Comparez les 2 hachages. S'ils sont identiques, l'utilisateur n'a modifié aucun champ du formulaire. S'ils sont différents, quelque chose a été modifié, et vous devez appeler votre code de persistance.

3 votes

C'est ce que j'attendais pour cette question. Y a-t-il une bibliothèque ?

3 votes

Le résultat ne serait-il pas le même si vous concaténiez tous les champs mais n'a pas Le hachage ?

0 votes

Oui, mais les données elles-mêmes pourraient être plus grandes que le hachage.

14voto

nikoskip Points 1371

Une autre façon d'y parvenir est de sérialiser le formulaire :

$(function() {
    var $form = $('form');
    var initialState = $form.serialize();

    $form.submit(function (e) {
      if (initialState === $form.serialize()) {
        console.log('Form is unchanged!');
      } else {
        console.log('Form has changed!');
      }
      e.preventDefault();
    });
});

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
Field 1: <input type="text" name="field_1" value="My value 1"> <br>
Field 2: <input type="text" name="field_2" value="My value 2"> <br>
Check: <input type="checkbox" name="field_3" value="1"><br>
<input type="submit">
</form>

10voto

AnthumChris Points 1778

Les modifications de formulaire peuvent facilement être détectées en JavaScript natif sans jQuery :

function initChangeDetection(form) {
  Array.from(form).forEach(el => el.dataset.origValue = el.value);
}
function formHasChanges(form) {
  return Array.from(form).some(el => 'origValue' in el.dataset && el.dataset.origValue !== el.value);
}

initChangeDetection() peut être appelé plusieurs fois tout au long du cycle de vie de votre page : Voir le test sur JSBin


Pour les anciens navigateurs qui ne prennent pas en charge les nouvelles fonctions de flèches et de tableaux :

function initChangeDetection(form) {
  for (var i=0; i<form.length; i++) {
    var el = form[i];
    el.dataset.origValue = el.value;
  }
}
function formHasChanges(form) {
  for (var i=0; i<form.length; i++) {
    var el = form[i];
    if ('origValue' in el.dataset && el.dataset.origValue !== el.value) {
      return true;
    }
  }
  return false;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X