如何知道表单输入已更改?

24
我有一个由<% Ajax.BeginForm() {} %>生成的表单,其中包含许多输入和文本区域。

当输入值更改时,我需要知道并标记输入和表单为“脏”。如果用户尝试离开页面而不保存,则会要求他或她确认放弃更改。

有任何建议如何完成这个过程吗?

5个回答

35

重新激活这个旧问题,因为我想到了一种更简单/更好的方法。不是监听各种输入事件,你可以将初始表单数据序列化、存储,然后稍后再次序列化并检查是否已更改,像这样:

var originalFormData = $('form#formId').serialize();
function checkFormChanged() {
    if(originalFormData !== $('form#formId').serialize()) {
        //it's dirty!
    }
}

另外一个优点是,如果用户进行了更改并且然后撤销了更改,这个检查将会把表单标记为干净。


2
这无疑是最好的答案。 - wingyip
一个不错的解决方案,但对于包含输入类型为文件的表单来说对我没起作用。 - Akshit Arora
1
这太聪明了,正是我所需要的!不需要循环输入或任何类似的东西。 - Bowiemtl

31

HTML控件包含一个属性,该属性保存原始值。您可以将此值与当前值进行比较,以查看是否有任何更改。

function getHasChanges() {
    var hasChanges = false;

    $(":input:not(:button):not([type=hidden])").each(function () {
        if ((this.type == "text" || this.type == "textarea" || this.type == "hidden") && this.defaultValue != this.value) {
            hasChanges = true;
            return false;             }
        else {
            if ((this.type == "radio" || this.type == "checkbox") && this.defaultChecked != this.checked) {
                hasChanges = true;
                return false;                 }
            else {
                if ((this.type == "select-one" || this.type == "select-multiple")) {
                    for (var x = 0; x < this.length; x++) {
                        if (this.options[x].selected != this.options[x].defaultSelected) {
                            hasChanges = true;
                            return false;
                        }
                    }
                }
            }
        }
    });

    return hasChanges;
}

function acceptChanges() {
    $(":input:not(:button):not([type=hidden])").each(function () {
        if (this.type == "text" || this.type == "textarea" || this.type == "hidden") {
            this.defaultValue = this.value;
        }
        if (this.type == "radio" || this.type == "checkbox") {
            this.defaultChecked = this.checked;
        }
        if (this.type == "select-one" || this.type == "select-multiple") {
            for (var x = 0; x < this.length; x++) {
                this.options[x].defaultSelected = this.options[x].selected
            }
        }
    });
}

我真的很喜欢这种检查值是否等于默认值的方法,我想这在“传统形式”中也可以正常工作。然而,我将通过XMLHttpRequest提交更改,并且当提交成功时,我需要“重置”表单。有没有一种好的方法可以将defaultValue/defaultChecked等设置为当前值? - tkalve
谢谢。我又进行了一些更改,加入了数字字段。 :) - Tadit Dash
点赞加速并使用"this"代替"$(this)"以获取纯JavaScript的"type"。 - Leo

26

来自 jQuery 文档:

//This applies to whole form
$('#formID').change(function() {
  alert('Form changed!');
});

你可以像这样仅检查输入并通知用户,如果他们尝试在保存更改之前退出。

var inputsChanged = false;
$('#formID input').change(function() {
  inputsChanged = true;
});

$(window).unload(function() {
  if (inputsChanged === true) {
    alert('Would you like to save your edits before exiting?'); 
  }    
});

jQuery API .change()


1
这对我非常有效。而且它比被接受的答案更简单,使用的代码更少。 - robskrob

9
我会使用jQuery来完成这个任务。代码可能类似于以下内容(这只是一个草稿,您可能需要添加/更改一些代码):
$(document).ready(function() {  
    $('#formId:input').each(function(key) {
        $(this).change(function() {
            $(this).addClass('dirty');
        });
    });
});

然后,在POST之前,请检查是否有脏输入。您甚至可以通过使用dirty css类来添加一些颜色。

编辑:已更正打字错误“changed”为“change”。


1
你可以使用 jQuery 插件 dirrty 来识别表单是否已更改。

https://github.com/rubentd/dirrty

在"dirty"事件中设置一些全局变量为true,以识别表单已更改。
处理window.onbeforeunload或$(window).unload()事件,并根据该变量值从用户那里获得确认。
这个插件的优点是你可以使用"clean"事件追踪表单是否再次更改回原始值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接