检测HTML表单上是否至少更改了一个字段的最简单方法是什么?

时间:2009-03-01 00:15:31

标签: javascript html

我有一个包含20多个字段的HTML表单。我还在页面上有几个链接,可以引导用户远离表单......可能没有保存任何更改。

我想警告(JS确认)用户onClick这些链接,如果任何表单字段已更改,但我不想创建一个巨大的switch语句,然后我需要维护,因为我添加新字段表格。我知道如何在Javascript中创建一个很长的'if'语句列表,命名每个字段并检查每个值,但如果我可以侥幸逃脱,我不想这样做。

检查用户是否更改了至少一个字段值的最简单方法是什么?

7 个答案:

答案 0 :(得分:68)

<强>方法

  1. 在显示表单(及其所有值)之前将其序列化(jQuery wayPrototype way
  2. "onbeforeunload"事件处理程序
  3. 中再次序列化它

    如果两者不匹配,则他们必须更改表单,因此从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;
            }
        }
    }