检测html表单是否被编辑的通用方法

Sat*_*hya 83 html javascript jquery

我有一个标签式的html表单.在从一个选项卡导航到另一个选项卡时,即使数据没有更改,当前选项卡的数据也会保留(在数据库上).

我想仅在编辑表单时才进行持久性调用.表单可以包含任何类型的控件.弄乱表单不需要输入一些文本,但在日历控件中选择日期也符合条件.

实现此目的的一种方法是默认情况下以只读模式显示表单并使用"编辑"按钮,如果用户单击编辑按钮,则会调用DB(再次,无论数据是否被修改)这是对现有技术的改进.

我想知道如何编写一个通用的javascript函数来检查是否有任何控件值被修改?

Phi*_*ert 143

在纯JavaScript中,这不是一件容易的事,但是jQuery使得它非常容易:

$("#myform :input").change(function() {
   $("#myform").data("changed",true);
});
Run Code Online (Sandbox Code Playgroud)

然后在保存之前,您可以检查它是否已更改:

if ($("#myform").data("changed")) {
   // submit the form
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,表单的id等于"myform".

如果您需要多种形式,可以轻松将其转换为插件:

$.fn.extend({
 trackChanges: function() {
   $(":input",this).change(function() {
      $(this.form).data("changed", true);
   });
 }
 ,
 isChanged: function() { 
   return this.data("changed"); 
 }
});
Run Code Online (Sandbox Code Playgroud)

然后你可以简单地说:

$("#myform").trackChanges();
Run Code Online (Sandbox Code Playgroud)

并检查表单是否已更改:

if ($("#myform").isChanged()) {
   // ...
}
Run Code Online (Sandbox Code Playgroud)

  • 这很简单.但是,如果用户更改表单输入然后还原更改(例如,通过单击复选框两次),则表单将被视为已修改.这是否可接受当然取决于具体情况.有关替代方案,请参阅http://stackoverflow.com/questions/10311663/find-out-if-html-form-has-changed (11认同)

Mat*_*nes 35

如果JQuery是不可能的.在Google上快速搜索发现了MD5和SHA1哈希算法的Javascript实现.如果您愿意,可以连接所有表单输入并对其进行哈希处理,然后将该值存储在内存中.当用户完成时.连接所有值并再次哈希.比较2个哈希值.如果它们相同,则用户不会更改任何表单字段.如果它们不同,则会编辑某些内容,您需要调用持久性代码.

  • 如果您连接所有字段但*没有*对其进行哈希处理,不是会得到相同的结果吗? (4认同)
  • 这就是我对这个问题的预期,有没有图书馆? (2认同)

mec*_*aph 13

我不确定我的问题是否正确,但是addEventListener呢?如果你不太关心IE8的支持,那应该没问题.以下代码适用于我:

var form = document.getElementById("myForm");

form.addEventListener("input", function () {
    console.log("Form has changed!");
});
Run Code Online (Sandbox Code Playgroud)


Ant*_*ris 9

无需 jQuery,就可以在原生 JavaScript 中轻松检测表单更改:

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);
}
Run Code Online (Sandbox Code Playgroud)


initChangeDetection()可以在页面的整个生命周期中安全地多次调用:请参阅 JSBin 上的测试


对于不支持新箭头/数组函数的旧浏览器:

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;
}
Run Code Online (Sandbox Code Playgroud)


Tee*_*kin 5

这是我的做法(不使用 jQuery)。

就我而言,我希望不计算一个特定的表单元素,因为它是触发检查的元素,因此总是会发生变化。异常元素被命名为“reporting_period”,并被硬编码在函数“hasFormChanged()”中。

要进行测试,请让一个元素调用函数“changeReportingPeriod()”,您可能希望将其命名为其他名称。

重要提示:当值设置为其原始值时(通常在页面加载时,但在我的情况下不是),您必须调用 setInitialValues()。

注意:我并不是说这是一个优雅的解决方案,事实上我不相信优雅的 JavaScript 解决方案。我个人对 JavaScript 的重视是可读性,而不是结构优雅(就好像这在 JavaScript 中是可能的一样)。在编写 JavaScript 时,我根本不关心文件大小,因为这就是 gzip 的用途,而尝试编写更紧凑的 JavaScript 代码总是会导致难以忍受的维护问题。我不道歉,不表示悔恨,也拒绝辩论。这是 JavaScript。抱歉,我必须说清楚这一点才能说服自己应该费心发帖。要开心!:)


    var initial_values = new Array();

    // Gets all form elements from the entire document.
    function getAllFormElements() {
        // Return variable.
        var all_form_elements = Array();

        // The form.
        var form_activity_report = document.getElementById('form_activity_report');

        // Different types of form elements.
        var inputs = form_activity_report.getElementsByTagName('input');
        var textareas = form_activity_report.getElementsByTagName('textarea');
        var selects = form_activity_report.getElementsByTagName('select');

        // We do it this way because we want to return an Array, not a NodeList.
        var i;
        for (i = 0; i < inputs.length; i++) {
            all_form_elements.push(inputs[i]);
        }
        for (i = 0; i < textareas.length; i++) {
            all_form_elements.push(textareas[i]);
        }
        for (i = 0; i < selects.length; i++) {
            all_form_elements.push(selects[i]);
        }

        return all_form_elements;
    }

    // Sets the initial values of every form element.
    function setInitialFormValues() {
        var inputs = getAllFormElements();
        for (var i = 0; i < inputs.length; i++) {
            initial_values.push(inputs[i].value);
        }
    }

    function hasFormChanged() {
        var has_changed = false;
        var elements = getAllFormElements();

        for (var i = 0; i < elements.length; i++) {
            if (elements[i].id != 'reporting_period' && elements[i].value != initial_values[i]) {
                has_changed = true;
                break;
            }
        }

        return has_changed;
    }

    function changeReportingPeriod() {
        alert(hasFormChanged());
    }


Run Code Online (Sandbox Code Playgroud)


nik*_*kip 5

实现此目的的另一种方法是序列化表格:

$(function() {
    var $form = $('form');
    var initialState = $form.serialize();
    
    $form.submit(function (e) {
      if (initialState === $form.serialize()) {
        console.log('Form is unchanged!');
      } else {
        console.log('Form has changed!');
      }
      e.preventDefault();
    });
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
Field 1: <input type="text" name="field_1" value="My value 1"> <br>
Field 2: <input type="text" name="field_2" value="My value 2"> <br>
Check: <input type="checkbox" name="field_3" value="1"><br>
<input type="submit">
</form>
Run Code Online (Sandbox Code Playgroud)