您如何处理jQuery中的表单更改?


81

在jQuery中,有没有一种简单的方法可以测试表单元素是否已更改?

编辑:我应该补充说,我只需要检查一个click()事件。

编辑:对不起,我真的应该更具体一些!说我有一个表单,并且有一个带有以下内容的按钮:

$('#mybutton').click(function() {
  // Here is where is need to test
  if(/* FORM has changed */) {
     // Do something
  }
});

自表单加载以来,如何测试表单是否已更改?


您是通过操作页面中包含的其他脚本还是在用户键入一些文本或单击单选按钮/复选框后立即执行操作?
FelipeAls 2010年

我应该补充一点,我只需要检查一下click()事件
麦克

Answers:


140

你可以这样做:

$("form :input").change(function() {
  $(this).closest('form').data('changed', true);
});
$('#mybutton').click(function() {
  if($(this).closest('form').data('changed')) {
     //do something
  }
});

这会触发change事件处理程序以表单形式输入内容,如果其中的任何更改将其用于.data()changed值设置为true,那么我们只需单击一下就可以检查该值,前提#mybutton是该值位于表单内部(如果不只是替换$(this).closest('form')$('#myForm')),但您可以使其更加通用,如下所示:

$('.checkChangedbutton').click(function() {
  if($(this).closest('form').data('changed')) {
     //do something
  }
});

参考:更新

根据jQuery,这是一个用于选择所有表单控件的过滤器。

http://api.jquery.com/input-selector/

:input选择器基本上选择所有表单控件。


6
是否$('form :input')考虑选择,文本区域和其他输入类型?还是特定于输入标签?
Val

6
如果我错了,请纠正我,但似乎该方法会说表格已经更改,即使有人进行了更改然后“撤消”了他们的更改,手动恢复了表格中的原始值。在这种情况下,表单实际上不会更改数据,但是此方法可以说已经更改。
保罗

1
谢谢,是的,我尝试了这一点(它在另一个答案中列出),但对我而言不起作用。似乎有些特殊情况也会使该方法失效。目前有一个插件工作- github.com/codedance/jquery.AreYouSure
保罗

1
对于这种情况很好的解决方案!但是,如果这里有人想要获取表单内容的状态(例如“ IsDirty”),则可能需要遵循以下解决方案:stackoverflow.com/a/26796840/665783
Jacob

1
@Nick Craver:如果表单元素在表单标签之外,且表单属性作为表单的id,该怎么办。我已经测试过了,不幸的是它没有用。
Mahantesh '19

49

如果要检查将要发送到服务器的表单数据是否已更改,可以在页面加载时序列化表单数据并将其与当前表单数据进行比较:

$(function() {

    var form_original_data = $("#myform").serialize(); 

    $("#mybutton").click(function() {
        if ($("#myform").serialize() != form_original_data) {
            // Something changed
        }
    });

});

5
太好了,这是这里最好的解决方案。谢谢。
2012年

3
我曾经使用过这种方法,当表格变大时,它变得非常缓慢。对于小型表单,这是一种好方法,但对于大型表单,则不是这样。
mkdevoogd

你是说表格里面有文件吗?
Udi 2013年

1
这很好,但是最好是,而不是每次检查控件更改时都直接检查表单将要提交的时间,而不是检查
Ruby Racer 2014年

2
这样好得多,因此您可以将按钮触发回禁用状态,例如“删除”
EliuX

29

实时,简单的解决方案:

$('form').on('keyup change paste', 'input, select, textarea', function(){
    console.log('Form changed!');
});

1
很好的解决方案。适用于您键入表单验证。
Bijan 2014年

1
对我来说最好的解决方案!非常感谢。
伊万

2
除非需要支持较旧的浏览器,否则请考虑使用'input'而不是'keyup change'处理鼠标右键粘贴。
TrueWill

10

您可以使用多个选择器将回调添加到任何表单元素的change事件。

$("input, select").change(function(){
    // Something changed
});

编辑

既然您提到您只需要单击一下,就可以简单地将我的原始代码修改为:

$("input, select").click(function(){
    // A form element was clicked
});

编辑#2

好的,您可以设置一个一旦发生如下更改即设置的全局变量:

var FORM_HAS_CHANGED = false;

$('#mybutton').click(function() {
    if (FORM_HAS_CHANGED) {
        // The form has changed
    }
});

$("input, select").change(function(){
    FORM_HAS_CHANGED = true;
});

3

看着更新的问题尝试类似

$('input, textarea, select').each(function(){
    $(this).data("val", $(this).val());
});
$('#button').click(function() {
    $('input, textarea, select').each(function(){
        if($(this).data("val")!==$(this).val()) alert("Things Changed");
    });
});

对于原始问题,请使用类似

$('input').change(function() {
    alert("Things have changed!");
});

这不检查<textarea><select>元素。
尼克·克拉弗

编辑后...这似乎需要大量工作和数据来回移动,boolean更改发生时,您所需要做的就是将其设置为true。此外,这仍然不是特定于表单的,如果页面中还有其他表单怎么办?
尼克·克拉弗

+1是一个不错的选择,但需要一些工作,将其绑定到表单并设置init。
匿名

这就是我认为正是:)(Y)的震撼
RK夏尔马


2

这是一个优雅的解决方案。

表单上每个输入元素都有一个隐藏属性,可用于确定该值是否已更改。每种类型的输入都有其自己的属性名称。例如

  • 因为text/textarea它是defaultValue
  • 因为select它是defaultSelect
  • 因为checkbox/radio它是defaultChecked

这是例子。

function bindFormChange($form) {

  function touchButtons() {
    var
      changed_objects = [],
      $observable_buttons = $form.find('input[type="submit"], button[type="submit"], button[data-object="reset-form"]');

    changed_objects = $('input:text, input:checkbox, input:radio, textarea, select', $form).map(function () {
      var
        $input = $(this),
        changed = false;

      if ($input.is('input:text') || $input.is('textarea') ) {
        changed = (($input).prop('defaultValue') != $input.val());
      }
      if (!changed && $input.is('select') ) {
        changed = !$('option:selected', $input).prop('defaultSelected');
      }
      if (!changed && $input.is('input:checkbox') || $input.is('input:radio') ) {
        changed = (($input).prop('defaultChecked') != $input.is(':checked'));
      }
      if (changed) {
        return $input.attr('id');
      }

    }).toArray();

    if (changed_objects.length) {
      $observable_buttons.removeAttr('disabled')   
    } else {
      $observable_buttons.attr('disabled', 'disabled');
    }
  };
  touchButtons();

  $('input, textarea, select', $form).each(function () {
    var $input = $(this);

    $input.on('keyup change', function () {
      touchButtons();
    });
  });

};

现在,只需遍历页面上的表单即可,默认情况下您应该会看到提交按钮处于禁用状态,并且仅当您确实会更改表单上的某些输入值时,它们才会被激活。

$('form').each(function () {
    bindFormChange($(this));
});

https://github.com/kulbida/jmodifiablejQuery在此处实现为插件


2
var formStr = JSON.stringify($("#form").serializeArray());
...
function Submit(){
   var newformStr = JSON.stringify($("#form").serializeArray());
   if (formStr != newformStr){
      ...
         formChangedfunct();
      ...
   }
   else {
      ...
         formUnchangedfunct();
      ...
   }
}

是的,这些年来,我什至不再使用jQuery。观察者和绑定一直到现在!不错,但是对于使用jQuery的任何人来说。
麦克,


1

扩展Udi的答案,这仅检查表单提交,而不检查每个输入更改。

$(document).ready( function () {
  var form_data = $('#myform').serialize();
  $('#myform').submit(function () {
      if ( form_data == $(this).serialize() ) {
        alert('no change');
      } else {
        alert('change');
      }
   });
});

0

首先,我将向表单添加隐藏的输入以跟踪表单的状态。然后,当表单上的某些内容发生更改时,我将使用此jQuery代码段设置隐藏输入的值:

    $("form")
    .find("input")
    .change(function(){
        if ($("#hdnFormChanged").val() == "no")
        {
            $("#hdnFormChanged").val("yes");
        }
    });

单击按钮时,可以检查隐藏输入的状态:

$("#Button").click(function(){
    if($("#hdnFormChanged").val() == "yes")
    {
        // handler code here...
    }
});

0

$('form[name="your_form_name"] input, form[name="your_form_name"] select').click(function() {
  $("#result").html($(this).val());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Form "your_form_name"</h2>
<form name="your_form_name">
  <input type="text" name="one_a" id="one_a" value="AAAAAAAA" />
  <input type="text" name="one_b" id="one_b" value="BBBBBBBB" />
  <input type="text" name="one_c" id="one_c" value="CCCCCCCC" />
  <select name="one_d">
    <option value="111111">111111</option>
    <option value="222222">222222</option>
    <option value="333333">333333</option>
  </select>
</form>
<hr/>
<h2>Form "your_other_form_name"</h2>
<form name="your_other_form_name">
  <input type="text" name="two_a" id="two_a" value="DDDDDDDD" />
  <input type="text" name="two_b" id="two_b" value="EEEEEEEE" />
  <input type="text" name="two_c" id="two_c" value="FFFFFFFF" />
  <input type="text" name="two_d" id="two_d" value="GGGGGGGG" />
  <input type="text" name="two_e" id="two_f" value="HHHHHHHH" />
  <input type="text" name="two_f" id="two_e" value="IIIIIIII" />
  <select name="two_g">
    <option value="444444">444444</option>
    <option value="555555">555555</option>
    <option value="666666">666666</option>
  </select>
</form>
<h2>Result</h2>
<div id="result">
  <h2>Click on a field..</h2>
</div>

除了以上@JoeD的答案。

如果您想以一种特定的形式(假设有多种形式)定位字段,而不仅仅是字段,则可以使用以下代码:

$('form[name="your_form_name"] input, form[name="your_form_name"] select').click(function() {
    // A form element was clicked
});

仅供参考,这可能不会做您想要的事情-它针对“ your_form_name”表单的输入元素,并在文档中进行所有选择。同样,出于性能原因,最好使用$ .fn.find而不是仅针对后代选择器,例如$('form').find('input,select')
dgo

@ user1167442如果我们有多个表格怎么办?我的示例是在一个页面中有多个表单的情况。
Anjana Silva '18

1
但是,仍然-您的示例将找到所有属于“ your_form_name”形式的子元素的输入元素,然后找到所有选择它们是“ your_form_name”形式的子元素还是所有形式的子元素。您的示例不适用于多种形式,除非您仅针对这些形式的选择。同样,如果您指的是演奏曲目,则最好使用$.fn.find-甚至$.fn.filter比引用速度更快-引用孩子而不是使用后代选择器。 vaughnroyko.com/the-real-scoop-on-jquery-find-performance
DGO

1
@ user1167442,您绝对正确。我错过了无论您使用哪种形式都将选择作为目标的事实。我已经纠正了这一点。非常感谢您指出。干杯!
Anjana Silva '18

0

试试这个:

<script>
var form_original_data = $("form").serialize(); 
var form_submit=false;
$('[type="submit"]').click(function() {
    form_submit=true;
});
window.onbeforeunload = function() {
    //console.log($("form").submit());
    if ($("form").serialize() != form_original_data && form_submit==false) {
        return "Do you really want to leave without saving?";
    }
};
</script>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.