Mam formularz HTML z zakładkami. Po przejściu z jednej karty do drugiej dane bieżącej karty są utrwalane (w bazie danych), nawet jeśli nie ma żadnych zmian w danych.
Chciałbym wykonać wywołanie trwałości tylko wtedy, gdy formularz jest edytowany. Formularz może zawierać dowolny rodzaj kontrolki. Zabrudzenie formularza nie musi polegać na wpisaniu jakiegoś tekstu, ale wybranie daty w kontrolce kalendarza również się kwalifikuje.
Jednym ze sposobów na osiągnięcie tego byłoby domyślne wyświetlanie formularza w trybie tylko do odczytu i posiadanie przycisku „Edytuj”, a jeśli użytkownik kliknie przycisk edycji, następuje wywołanie bazy danych (jeszcze raz, niezależnie od tego, czy dane są modyfikowane .To lepsze ulepszenie tego, co obecnie istnieje).
Chciałbym wiedzieć, jak napisać ogólną funkcję javascript, która sprawdzałaby, czy któraś z wartości kontrolnych została zmodyfikowana?
źródło
Odpowiedzi:
W czystym javascript nie byłoby to łatwe zadanie, ale jQuery sprawia, że jest to bardzo łatwe:
$("#myform :input").change(function() { $("#myform").data("changed",true); });
Następnie przed zapisaniem możesz sprawdzić, czy zostało zmienione:
if ($("#myform").data("changed")) { // submit the form }
W powyższym przykładzie identyfikator formularza jest równy „myform”.
Jeśli potrzebujesz tego w wielu formach, możesz łatwo przekształcić go we wtyczkę:
$.fn.extend({ trackChanges: function() { $(":input",this).change(function() { $(this.form).data("changed", true); }); } , isChanged: function() { return this.data("changed"); } });
Następnie możesz po prostu powiedzieć:
$("#myform").trackChanges();
i sprawdź, czy formularz się zmienił:
if ($("#myform").isChanged()) { // ... }
źródło
trackChanges: function () { $(document).on('change', $(this).find(':input'), function (e) { var el = $(e.target); $(el).closest('form').data("changed", true); });
W przypadku, gdy JQuery nie wchodzi w grę. Szybkie wyszukiwanie w Google znalazło implementacje algorytmów mieszania MD5 i SHA1 w Javascript. Jeśli chcesz, możesz połączyć wszystkie dane wejściowe formularza i zhaszować je, a następnie zapisać tę wartość w pamięci. Kiedy użytkownik skończy. Połącz ponownie wszystkie wartości i hash. Porównaj 2 skróty. Jeśli są takie same, użytkownik nie zmienił żadnych pól formularza. Jeśli są różne, coś zostało zmodyfikowane i musisz wywołać swój kod trwałości.
źródło
Nie jestem pewien, czy dobrze odpowiem na Twoje pytanie, ale co z addEventListener? Jeśli nie przejmujesz się zbytnio obsługą IE8, powinno to wystarczyć. Poniższy kod działa dla mnie:
var form = document.getElementById("myForm"); form.addEventListener("input", function () { console.log("Form has changed!"); });
źródło
Innym sposobem osiągnięcia tego jest serializacja formularza:
$(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>
źródło
serialize()
że nie będzie zawierałdisabled
elementów. Może być OK w wielu przypadkach, ale może stanowić problem w innych przypadkach.Oto jak to zrobiłem (bez użycia jQuery).
W moim przypadku chciałem, aby jeden element formularza nie był liczony, ponieważ był to element, który wyzwalał sprawdzanie i zawsze będzie się zmieniać. Wyjątkowy element nosi nazwę „okres_raportowania” i jest zakodowany na stałe w funkcji „hasFormChanged ()”.
Aby przetestować, spraw, aby element wywołał funkcję „changeReportingPeriod ()”, której prawdopodobnie będziesz chciał nazwać coś innego.
WAŻNE: musisz wywołać metodę setInitialValues (), gdy wartości zostały ustawione na ich oryginalne wartości (zwykle podczas ładowania strony, ale nie w moim przypadku).
UWAGA: Nie twierdzę, że jest to eleganckie rozwiązanie, tak naprawdę nie wierzę w eleganckie rozwiązania JavaScript. Mój osobisty nacisk w JavaScript kładzie się na czytelność, a nie na strukturalną elegancję (tak jakby było to możliwe w JavaScript). Nie przejmuję się w ogóle rozmiarem pliku podczas pisania JavaScript, ponieważ do tego służy gzip, a próba napisania bardziej zwartego kodu JavaScript niezmiennie prowadzi do nieznośnych problemów z konserwacją. Nie przepraszam, nie wyrażam wyrzutów sumienia i odmawiam dyskusji. To jest JavaScript. Przepraszam, musiałem to wyjaśnić, aby przekonać się, że powinienem zawracać sobie głowę wysyłaniem. Bądź szczęśliwy! :)
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()); }
źródło
Zmiany formularzy można łatwo wykryć w natywnym JavaScript bez 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()
można bezpiecznie wywoływać wiele razy w całym cyklu życia strony: zobacz Testowanie w JSBinW przypadku starszych przeglądarek, które nie obsługują nowszych funkcji strzałek / tablic:
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; }
źródło
Oto demonstracja metody polyfill w natywnym języku JavaScript, która wykorzystuje
FormData()
interfejs API do wykrywania utworzonych, zaktualizowanych i usuniętych wpisów formularzy. Możesz sprawdzić, czy cokolwiek zostało zmienione za pomocąHTMLFormElement#isChanged
i pobrać obiekt zawierający różnice z formularza resetowania za pomocąHTMLFormElement#changes
(zakładając, że nie są one maskowane przez nazwę wejściową):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>
źródło