Saya memiliki formulir html tab. Setelah menavigasi dari satu tab ke tab lainnya, data tab saat ini tetap ada (pada DB) bahkan jika tidak ada perubahan pada data.
Saya ingin membuat panggilan ketekunan hanya jika formulir diedit. Formulir dapat berisi segala jenis kontrol. Mengotori formulir tidak perlu dengan mengetik beberapa teks tetapi memilih tanggal dalam kontrol kalender juga memenuhi syarat.
Salah satu cara untuk mencapai hal ini adalah dengan menampilkan formulir dalam mode hanya-baca secara default dan memiliki tombol 'Edit' dan jika pengguna mengklik tombol edit maka panggilan ke DB dilakukan (sekali lagi, terlepas dari apakah data diubah Ini adalah peningkatan yang lebih baik dari apa yang ada saat ini).
Saya ingin tahu cara menulis fungsi javascript generik yang akan memeriksa apakah ada nilai kontrol yang telah dimodifikasi?
sumber
Jawaban:
Dalam javascript murni, ini bukanlah tugas yang mudah, tetapi jQuery membuatnya sangat mudah untuk dilakukan:
$("#myform :input").change(function() { $("#myform").data("changed",true); });
Kemudian sebelum menyimpan, Anda dapat memeriksa apakah sudah diubah:
if ($("#myform").data("changed")) { // submit the form }
Dalam contoh di atas, formulir memiliki id yang sama dengan "myform".
Jika Anda membutuhkan ini dalam berbagai bentuk, Anda dapat dengan mudah mengubahnya menjadi plugin:
$.fn.extend({ trackChanges: function() { $(":input",this).change(function() { $(this.form).data("changed", true); }); } , isChanged: function() { return this.data("changed"); } });
Kemudian Anda cukup mengatakan:
$("#myform").trackChanges();
dan periksa apakah formulir telah berubah:
if ($("#myform").isChanged()) { // ... }
sumber
trackChanges: function () { $(document).on('change', $(this).find(':input'), function (e) { var el = $(e.target); $(el).closest('form').data("changed", true); });
Jika JQuery keluar dari pertanyaan. Pencarian cepat di Google menemukan implementasi Javascript dari algoritma hash MD5 dan SHA1. Jika mau, Anda dapat menggabungkan semua input formulir dan mencirikannya, lalu menyimpan nilai itu di memori. Saat pengguna selesai. Gabungkan semua nilai dan hash lagi. Bandingkan 2 hash. Jika keduanya sama, pengguna tidak mengubah bidang formulir apa pun. Jika berbeda, ada sesuatu yang telah diedit, dan Anda perlu memanggil kode ketekunan Anda.
sumber
Saya tidak yakin apakah pertanyaan Anda benar, tetapi bagaimana dengan addEventListener? Jika Anda tidak terlalu peduli tentang dukungan IE8 ini seharusnya baik-baik saja. Kode berikut berfungsi untuk saya:
var form = document.getElementById("myForm"); form.addEventListener("input", function () { console.log("Form has changed!"); });
sumber
Cara lain untuk mencapai ini adalah membuat formulir berseri:
$(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>
sumber
Inilah cara saya melakukannya (tanpa menggunakan jQuery).
Dalam kasus saya, saya ingin satu elemen bentuk tertentu tidak dihitung, karena itu adalah elemen yang memicu pemeriksaan dan akan selalu berubah. Elemen luar biasa dinamai 'reporting_period' dan di-hardcode dalam fungsi 'hasFormChanged ()'.
Untuk mengujinya, buat sebuah elemen memanggil fungsi "changeReportingPeriod ()", yang mungkin Anda ingin beri nama lain.
PENTING: Anda harus memanggil setInitialValues () ketika nilai telah disetel ke nilai aslinya (biasanya saat pemuatan halaman, tetapi tidak dalam kasus saya).
CATATAN: Saya tidak mengklaim bahwa ini adalah solusi yang elegan, sebenarnya saya tidak percaya pada solusi JavaScript yang elegan. Penekanan pribadi saya dalam JavaScript adalah pada keterbacaan, bukan keanggunan struktural (seolah-olah itu mungkin dalam JavaScript). Saya tidak menyibukkan diri dengan ukuran file sama sekali saat menulis JavaScript karena untuk itulah gzip, dan mencoba menulis kode JavaScript yang lebih ringkas selalu mengarah pada masalah pemeliharaan yang tidak dapat ditoleransi. Saya tidak menawarkan permintaan maaf, tidak mengungkapkan penyesalan dan menolak untuk memperdebatkannya. Ini JavaScript. Maaf, saya harus menjelaskan ini untuk meyakinkan diri sendiri bahwa saya perlu repot-repot memposting. Berbahagialah! :)
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()); }
sumber
Perubahan formulir dapat dengan mudah dideteksi dalam JavaScript asli tanpa 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()
dapat dipanggil dengan aman beberapa kali sepanjang siklus hidup halaman Anda: Lihat Menguji di JSBinUntuk browser lama yang tidak mendukung fungsi panah / larik yang lebih baru:
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; }
sumber
Berikut demo metode polyfill dalam JavaScript asli yang menggunakan
FormData()
API untuk mendeteksi entri formulir yang dibuat, diperbarui, dan dihapus. Anda dapat memeriksa apakah ada yang diubah menggunakanHTMLFormElement#isChanged
dan mendapatkan objek yang berisi perbedaan dari formulir reset menggunakanHTMLFormElement#changes
(dengan asumsi mereka tidak ditutupi oleh nama input):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>
sumber