J'ai un formulaire HTML à onglets. Lors de la navigation d'un onglet à l'autre, les données de l'onglet actuel sont conservées (sur la base de données) même s'il n'y a pas de modification des données.
Je souhaite effectuer l'appel de persistance uniquement si le formulaire est modifié. Le formulaire peut contenir tout type de contrôle. Il n'est pas nécessaire de salir le formulaire en tapant du texte, mais le choix d'une date dans un contrôle de calendrier serait également admissible.
Une façon d'y parvenir serait d'afficher le formulaire en mode lecture seule par défaut et d'avoir un bouton `` Modifier '' et si l'utilisateur clique sur le bouton d'édition, l'appel à la base de données est effectué (encore une fois, que les données soient modifiées ou non C'est une meilleure amélioration par rapport à ce qui existe actuellement).
Je voudrais savoir comment écrire une fonction javascript générique qui vérifierait si l'une des valeurs des contrôles a été modifiée?
la source
Réponses:
En javascript pur, ce ne serait pas une tâche facile, mais jQuery le rend très facile à faire:
$("#myform :input").change(function() { $("#myform").data("changed",true); });
Ensuite, avant d'enregistrer, 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 identifiant égal à "myform".
Si vous en avez besoin sous de nombreuses formes, vous pouvez facilement le transformer en plugin:
$.fn.extend({ trackChanges: function() { $(":input",this).change(function() { $(this.form).data("changed", true); }); } , isChanged: function() { return this.data("changed"); } });
Ensuite, vous pouvez simplement dire:
$("#myform").trackChanges();
et vérifiez si un formulaire a changé:
if ($("#myform").isChanged()) { // ... }
la source
trackChanges: function () { $(document).on('change', $(this).find(':input'), function (e) { var el = $(e.target); $(el).closest('form').data("changed", true); });
Au cas où JQuery serait hors de question. Une recherche rapide sur Google a trouvé 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énez toutes les valeurs et hachez à nouveau. Comparez les 2 hachages. S'ils sont identiques, l'utilisateur n'a modifié aucun champ de formulaire. S'ils sont différents, quelque chose a été modifié et vous devez appeler votre code de persistance.
la source
Je ne sais pas si j'ai bien répondu à votre question, mais qu'en est-il de addEventListener? Si vous ne vous souciez pas trop du support IE8, cela devrait être bien. Le code suivant fonctionne pour moi:
var form = document.getElementById("myForm"); form.addEventListener("input", function () { console.log("Form has changed!"); });
la source
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>
la source
Voici comment je l'ai fait (sans utiliser jQuery).
Dans mon cas, je voulais qu'un élément de formulaire particulier ne soit pas compté, car c'est l'élément qui a déclenché la vérification et il aura donc toujours changé. L'élément exceptionnel est nommé 'reporting_period' et est codé en dur dans la fonction 'hasFormChanged ()'.
Pour tester, faites un élément appeler la fonction "changeReportingPeriod ()", que vous voudrez probablement nommer autre chose.
IMPORTANT: vous devez appeler setInitialValues () lorsque les valeurs ont été définies sur leurs valeurs d'origine (généralement au chargement de la page, mais pas dans mon cas).
REMARQUE: je ne prétends pas que ce soit une solution élégante, en fait je ne crois pas aux solutions JavaScript élégantes. Mon accent personnel en JavaScript est la lisibilité, pas l'élégance structurelle (comme si cela était possible en JavaScript). Je ne me préoccupe pas du tout de la taille du fichier lors de l'écriture de JavaScript, car c'est à cela que sert gzip, et essayer d'écrire du code JavaScript plus compact conduit invariablement à des problèmes de maintenance intolérables. Je ne présente aucune excuse, n'exprime aucun remords et refuse d'en débattre. C'est du JavaScript. Désolée, je devais clarifier cela pour me convaincre que je devrais prendre la peine de poster. Soyez heureux! :)
var initial_values = new Array(); // Gets all form elements from the entire document. function getAllFormElements() { // Return variable. var all_form_elements = Array(); // The form. var form_activity_report = document.getElementById('form_activity_report'); // Different types of form elements. var inputs = form_activity_report.getElementsByTagName('input'); var textareas = form_activity_report.getElementsByTagName('textarea'); var selects = form_activity_report.getElementsByTagName('select'); // We do it this way because we want to return an Array, not a NodeList. var i; for (i = 0; i < inputs.length; i++) { all_form_elements.push(inputs[i]); } for (i = 0; i < textareas.length; i++) { all_form_elements.push(textareas[i]); } for (i = 0; i < selects.length; i++) { all_form_elements.push(selects[i]); } return all_form_elements; } // Sets the initial values of every form element. function setInitialFormValues() { var inputs = getAllFormElements(); for (var i = 0; i < inputs.length; i++) { initial_values.push(inputs[i].value); } } function hasFormChanged() { var has_changed = false; var elements = getAllFormElements(); for (var i = 0; i < elements.length; i++) { if (elements[i].id != 'reporting_period' && elements[i].value != initial_values[i]) { has_changed = true; break; } } return has_changed; } function changeReportingPeriod() { alert(hasFormChanged()); }
la source
Les modifications de formulaire peuvent facilement être détectées dans 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é en toute sécurité plusieurs fois tout au long du cycle de vie de votre page: voir Test sur JSBinPour les navigateurs plus anciens qui ne prennent pas en charge les nouvelles fonctions de flèche / tableau:
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; }
la source
Voici une démonstration de la méthode polyfill en JavaScript natif qui utilise l'
FormData()
API pour détecter les entrées de formulaire créées, mises à jour et supprimées. Vous pouvez vérifier si quelque chose a été modifié en utilisantHTMLFormElement#isChanged
et obtenir un objet contenant les différences d'un formulaire de réinitialisation en utilisantHTMLFormElement#changes
(en supposant qu'ils ne soient pas masqués par un nom d'entrée):Object.defineProperties(HTMLFormElement.prototype, { isChanged: { configurable: true, get: function isChanged () { 'use strict' var thisData = new FormData(this) var that = this.cloneNode(true) // avoid masking: https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reset HTMLFormElement.prototype.reset.call(that) var thatData = new FormData(that) const theseKeys = Array.from(thisData.keys()) const thoseKeys = Array.from(thatData.keys()) if (theseKeys.length !== thoseKeys.length) { return true } const allKeys = new Set(theseKeys.concat(thoseKeys)) function unequal (value, index) { return value !== this[index] } for (const key of theseKeys) { const theseValues = thisData.getAll(key) const thoseValues = thatData.getAll(key) if (theseValues.length !== thoseValues.length) { return true } if (theseValues.some(unequal, thoseValues)) { return true } } return false } }, changes: { configurable: true, get: function changes () { 'use strict' var thisData = new FormData(this) var that = this.cloneNode(true) // avoid masking: https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reset HTMLFormElement.prototype.reset.call(that) var thatData = new FormData(that) const theseKeys = Array.from(thisData.keys()) const thoseKeys = Array.from(thatData.keys()) const created = new FormData() const deleted = new FormData() const updated = new FormData() const allKeys = new Set(theseKeys.concat(thoseKeys)) function unequal (value, index) { return value !== this[index] } for (const key of allKeys) { const theseValues = thisData.getAll(key) const thoseValues = thatData.getAll(key) const createdValues = theseValues.slice(thoseValues.length) const deletedValues = thoseValues.slice(theseValues.length) const minLength = Math.min(theseValues.length, thoseValues.length) const updatedValues = theseValues.slice(0, minLength).filter(unequal, thoseValues) function append (value) { this.append(key, value) } createdValues.forEach(append, created) deletedValues.forEach(append, deleted) updatedValues.forEach(append, updated) } return { created: Array.from(created), deleted: Array.from(deleted), updated: Array.from(updated) } } } }) document.querySelector('[value="Check"]').addEventListener('click', function () { if (this.form.isChanged) { console.log(this.form.changes) } else { console.log('unchanged') } })
<form> <div> <label for="name">Text Input:</label> <input type="text" name="name" id="name" value="" tabindex="1" /> </div> <div> <h4>Radio Button Choice</h4> <label for="radio-choice-1">Choice 1</label> <input type="radio" name="radio-choice-1" id="radio-choice-1" tabindex="2" value="choice-1" /> <label for="radio-choice-2">Choice 2</label> <input type="radio" name="radio-choice-2" id="radio-choice-2" tabindex="3" value="choice-2" /> </div> <div> <label for="select-choice">Select Dropdown Choice:</label> <select name="select-choice" id="select-choice"> <option value="Choice 1">Choice 1</option> <option value="Choice 2">Choice 2</option> <option value="Choice 3">Choice 3</option> </select> </div> <div> <label for="textarea">Textarea:</label> <textarea cols="40" rows="8" name="textarea" id="textarea"></textarea> </div> <div> <label for="checkbox">Checkbox:</label> <input type="checkbox" name="checkbox" id="checkbox" /> </div> <div> <input type="button" value="Check" /> </div> </form>
la source