我使用jquery给表单添加了一个change事件处理程序。当任何输入框被更改时,它都能正常工作。但是,如果某些其他代码更改输入框的值,它就不能正常工作。
是否有办法检测表单是否已更改,即使其输入框的值已经被代码更改了?
我使用jquery给表单添加了一个change事件处理程序。当任何输入框被更改时,它都能正常工作。但是,如果某些其他代码更改输入框的值,它就不能正常工作。
是否有办法检测表单是否已更改,即使其输入框的值已经被代码更改了?
是的,关于这个问题似乎存在一些混淆。在理想情况下,您期望当输入内容发生更改时,onchange事件会发生,但事实并非如此。我相信这样做有充分的理由 - 也许不是。
我克服这个障碍的方法之一是将表单状态捕获到变量中,在显示表单后和提交表单前检查状态是否已更改,并根据情况采取行动。
一个易于存储的状态是serialize函数返回的内容。一个方便的地方来存储该状态是使用data功能。jquery提供了serialize和data两种方式。
当然,您可以使用其他不同形式的状态(某种哈希)或存储此状态的存储器(例如标准全局变量)。
这是一些原型代码:
如果您的表单id为“xform”,则可以在表单显示时调用以下代码:
$('#xform').data('serialize',$('#xform').serialize());
然后,当你需要检查时,例如在按钮提交之前,你可以使用以下代码:
if($('#xform').serialize()!=$('#xform').data('serialize')){
// Form has changed!!!
}
你可以将所有这些内容封装成一个复制并粘贴的JavaScript代码片段,该代码片段将为您提供一个formHasChanged()
函数,您可以在需要时调用它(未经测试):
你可以把这一切都整合到一个复制并粘贴的 JavaScript 代码片段中,这样就可以得到一个名为formHasChanged()
的函数,并且可以在需要的地方调用它(未经测试):
$(function() {
$('#xform').data('serialize',$('#xform').serialize());
});
function formHasChanged(){
if($('#xform').serialize()!=$('#xform').data('serialize')){
return(true);
}
return(false);
}
但是如果继续下去,我会再次创建另一个jQuery插件。
将表单序列化肯定是一种选择,但如果:
幸运的是,每个表单元素都有与其对象相关联的默认值:
例如:要检查输入框或文本区域是否已更改,请使用:
var changed = false;
$(":text,textarea").each(function(){
changed = this.value != this.defaultValue;
return !changed; // return if at least one control has changed value
});
在JavaScript中,可以轻松实现此操作而无需使用jQuery。initChangeDetection()
可以被多次调用:
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);
}
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;
}
.value
无法告诉你一个 checkbox
或 radio
输入是否已更改。在这些情况下,需要使用 .checked
。 - xr280xr不是常规的方式。
您可以通过更改输入并触发更改事件来进行更改。
$('#inputId').val('foo').trigger('change');
或者使用这个:
$('#inputId').val('foo').change();
trigger('change')
或change()
。 - thecodeparadoxfunction initFormHash(form) {
form.setAttribute("data-initial-hash", getFormHash(form));
}
function getFormHash(form) {
const formValues = {};
form.querySelectorAll("input").forEach(input => {
const inputType = input.getAttribute("type");
const inputName = input.getAttribute("name");
if (inputType === "hidden") return;
if (!inputName) return;
if (inputType === "checkbox" || inputType == "radio") {
formValues[inputName] = input.checked;
return;
}
formValues[inputName] = input.value;
});
form.querySelectorAll("textarea, select").forEach(textarea => {
const name = textarea.getAttribute("name");
if (!name) return;
formValues[name] = textarea.value;
})
return JSON.stringify(formValues);
}
function formChanged(form) {
return (form.getAttribute("data-initial-hash") !== getFormHash(form));
}
这是我做的(我找到了我的解决方案,使用了zaf的答案)
$("form").change(function() {
$(this).data("changed","true");
});
$("input[type='submit']").click(function() {
if($("form").data("changed") == "true") {
var discard = confirm("Some unsaved changes. Discard them ?");
if(!discard) return false;
}
});
return confirm("...");
语句,但我认为那样会更难阅读。 - Xeltoronchange
属性,根据W3C的文档,它应该在元素内容、选择或选中状态发生改变时触发。onchange
属性一样,但是分离关注点。 - gdoron
HTMLElement.dataSet
(.data()
,但是原生)和传递给URLSearchParams
的FormData
(序列化,但是原生)。现在没有任何借口使用Internet Explorer 6了。抱歉,我是指jQuery。因为IE6是为其而补偿的。 - amcgregorHTMLElement.dataSet
(.data()
,但是原生的)和通过URLSearchParams
传递给FormData
(序列化,但是原生的)。实际答案也被投票降低了。现在没有使用Internet Explorer 6的借口了(https://gist.github.com/amcgregor/d6ea618b772b52bb288cff72c8381640#jquery)。抱歉,我是指jQuery。因为IE6是它的补偿。 - undefined