我有一个包含20多个字段的HTML表单。我还在页面上有几个链接,可以引导用户远离表单......可能没有保存任何更改。
我想警告(JS确认)用户onClick这些链接,如果任何表单字段已更改,但我不想创建一个巨大的switch语句,然后我需要维护,因为我添加新字段表格。我知道如何在Javascript中创建一个很长的'if'语句列表,命名每个字段并检查每个值,但如果我可以侥幸逃脱,我不想这样做。
检查用户是否更改了至少一个字段值的最简单方法是什么?
答案 0 :(得分:68)
<强>方法强>
"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.';
}
};
答案 1 :(得分:11)
我很确定这是一个坏主意,但我想把它扔出去。
表单字段可以获取“默认值”(即字段加载时的值),您可以将其与当前值进行比较。如果向表单添加字段,则对所有字段的简单循环将消除维护需求。
可能存在或不存在与“默认值”属性相关联的各种浏览器错误,因此如果不进行大量测试,我将不相信此方法。下面的代码是概念证明,在任何实际应用中都没有(由我)使用。
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;
}
答案 2 :(得分:8)
使用jQuery这很容易。您应该能够使用相同的前提来在vanilla javascript中实现相同的结果。
var $inps = $('#myForm').find('input,select,textarea')
, formAltered = false
;
$inps.change(function() {
formAltered = true;
$inps.unbind('change'); // saves this function running every time.
});
唯一的问题是,如果您更改某个值,然后将其更改回原始值,它仍会将该表单报告为已更改。
答案 3 :(得分:5)
以下是您可以添加到表单的单行内容:
$(':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);
这不会检查表单的值是否不同,只有用户更改了表单。但是,它简单易用。
答案 4 :(得分:3)
这可以用一个布尔变量来处理,我们称之为脏位处理。如果您通常在网页中观察到,一旦用户对任何字段执行某些编辑操作,表单将被视为脏(编辑)(即使编辑后数据保持不变)。当用户尝试离开页面时,系统会提示用户是否要保存更改。
根据标准惯例,如果实际更改了值,则无法检查是否在编辑某个字段后。例如:如果用户编辑并将“xyz”附加到文本字段然后删除“xyz”,则表单数据基本保持不变,但表单仍被视为“脏”,并且当用户提示时会显示警告消息试图离开。
所以,如果你想实现这个东西变得非常简单。您只需要在控件中添加onchange()事件处理程序,并在这些事件处理程序中将全局布尔变量设置为类似于isDirty的值。
一旦用户想要离开,您可以闪烁一条消息“当前页面上可能有未保存的更改。您要保存它们吗?”。即使用户注意到他的编辑没有改变初始数据,用户也不会失望。
上面给出的答案实现了这种行为。我之所以写这篇是因为你似乎有一个想法,就是通过它的初始值来检查每个字段,看它是否在编辑后真的被改变了。只是想告诉你,根本不需要检查每个字段。
答案 5 :(得分:0)
就我而言,我将@Crescent Fresh和@nickf答案结合在一起,得到了这个答案:
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', '');
}
});
答案 6 :(得分:0)
多年来发布的答案已经证明了自己(经过一些小的改进)。这是我在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;
}
}
}