我有一个包含20多个字段的HTML表单。页面上还有一些链接,可能会在没有保存任何更改的情况下将用户导向其他页面。
当用户点击这些链接时,我想通过JS确认警告用户,如果其中任何一个表单字段已更改,但我不想创建一个庞大的开关语句,然后需要维护它来添加新字段到表单中。我知道如何在Javascript中创建长列表的“if”语句,命名每个字段并检查每个值,但如果可以避免,我不想这样做。
最简单的方法是如何检查用户是否更改了至少一个字段值?
我有一个包含20多个字段的HTML表单。页面上还有一些链接,可能会在没有保存任何更改的情况下将用户导向其他页面。
当用户点击这些链接时,我想通过JS确认警告用户,如果其中任何一个表单字段已更改,但我不想创建一个庞大的开关语句,然后需要维护它来添加新字段到表单中。我知道如何在Javascript中创建长列表的“if”语句,命名每个字段并检查每个值,但如果可以避免,我不想这样做。
最简单的方法是如何检查用户是否更改了至少一个字段值?
做法
"onbeforeunload"
事件处理程序中再次序列化。如果两者不匹配,则必须更改了表单,因此从您的 onbeforeunload
处理程序返回字符串(例如 "您有未保存的数据")。
这种方法允许表单字段发展,同时“确认是否更改”逻辑保持不变。
示例 (混合javascript和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.';
}
};
我非常确定这是一个不好的想法,但我想提出来。
表单字段有一种获取“默认值”的方法(即加载字段时该字段具有的值),您可以将其与当前值进行比较。简单地循环所有字段可消除添加表单字段时需要维护的麻烦。
可能会存在与“默认值”属性相关的各种浏览器错误,因此如果没有经过广泛测试,我不会信任此方法。下面的代码是概念验证,并未在任何实际应用程序中使用(由我)。
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;
}
var $inps = $('#myForm').find('input,select,textarea')
, formAltered = false
;
$inps.change(function() {
formAltered = true;
$inps.unbind('change'); // saves this function running every time.
});
唯一的问题是,如果你更改了一个值,然后将其改回原始值,它仍会报告表单已更改。
var $inps = $('#myForm :input'), formAltered = false;
- ANeves以下是您可以添加到表单中的一行代码:
$(':input',document.myForm).bind("change", function() {
enablePrompt(true); }); // Prevent accidental navigation away
然后,您可以为整个网站创建enableUnloadPrompt()函数:
function enablePrompt(enabled) {
window.onbeforeunload = enabled ? "Your changes are not saved!" : null;
}
enablePrompt(false);
这将不会检查表单的值是否不同,只是检查用户是否曾经更改过表单。但是,它非常简单易用。
var formBefore;
var $inps = $('form').find('input,select,textarea');
$(function() {
formBefore = $("form").serialize();
});
$inps.change(function () {
var changedForm = $("form").serialize();
if (formBefore != changedForm) {
$("#btnSave").css('background-color', 'green');
} else {
$("#btnSave").css('background-color', '');
}
});
$("#btnSave").css('background-color', '');
- andymnclet formBefore;
let $inps = $('form :input');
$("#btnSave").prop("disabled", true );
$(function() {
formBefore = $("form").serialize();
});
$inps.change(function () {
var changedForm = $("form").serialize();
if (formBefore != changedForm) {
$("#btnSave").prop("disabled", false);
} else {
$("#btnSave").css('background-color', '');
$("#btnSave").prop("disabled", true );
}
});
- andymnc之前发布的答案经过一些小改进后已经在这些年中证明了自己。这是我在onBeforeUnload事件函数中使用的函数。
/*
** Determines if a form is dirty by comparing the current
** value of each element with its default value.
**
** @param {Form} form the form to be checked.
** @return {Boolean} true if the form is dirty, false otherwise.
*/
function formIsDirty(form) {
for (var i = 0; i < form.elements.length; i++) {
var element = form.elements[i];
var type = element.type;
switch (element.type) {
case "checkbox":
case "radio":
if (element.checked != element.defaultChecked)
return true;
break;
case "number":
case "hidden":
case "password":
case "date":
case "text":
case "textarea":
if (element.value != element.defaultValue)
return true;
break;
case "select-one":
case "select-multiple":
for (var j = 0; j < element.options.length; j++)
if (element.options[j].selected != element.options[j].defaultSelected)
return true;
break;
}
}
return false;
}
这里是一个onBeforeUnload处理函数的示例:
function onBeforeUnload(event) {
event = event || window.event;
for (i = 0; i < document.forms.length; i++) {
switch (document.forms[i].id) {
case "search":
break;
default:
if (formIsDirty(document.forms[i])) {
if (event)
event.returnValue = "You have unsaved changes.";
return "You have unsaved changes.";
}
break;
}
}
}
<form>
标签具有onChange
回调函数,每当任何字段触发onChange
事件时都会触发。
示例:
<form onChange={isDirtyFunc}>
<input name="name" type="text"/>
<input name="address" type="text"/>
<input name="age" type="number"/>
</form>
如果任何字段发生更改,则使用相关事件调用isDirtyFunc
函数。
var form_clean = $("form").serialize();
吗? - Edd