Làm thế nào để bạn xử lý một thay đổi biểu mẫu trong jQuery?


81

Trong jQuery, có cách đơn giản nào để kiểm tra xem BẤT KỲ phần tử nào của biểu mẫu đã thay đổi không?

CHỈNH SỬA: Tôi lẽ ra phải nói thêm rằng tôi chỉ cần kiểm tra một click()sự kiện.

CHỈNH SỬA: Xin lỗi, tôi thực sự nên cụ thể hơn! Giả sử tôi có một biểu mẫu và tôi có một nút với nội dung sau:

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

Làm cách nào để kiểm tra xem biểu mẫu đã thay đổi kể từ khi nó được tải hay chưa?


Ý của bạn là do hành động của một số tập lệnh khác có trong trang hoặc ngay sau khi người dùng nhập một số văn bản hoặc nhấp vào radio / hộp kiểm?
FelipeAls

Tôi lẽ ra phải nói thêm rằng tôi chỉ cần kiểm tra sự kiện click ()
mike

Câu trả lời:


140

Bạn có thể làm được việc này:

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

Giàn khoan này change trình xử lý sự kiện đối với các đầu vào trong biểu mẫu, nếu bất kỳ người nào trong số họ thay đổi, nó sẽ sử dụng .data()để đặt changedgiá trị thành true, khi đó chúng tôi chỉ kiểm tra giá trị đó khi nhấp chuột, điều này giả định rằng nó #mybuttonnằm bên trong biểu mẫu (nếu không chỉ thay thế $(this).closest('form')bằng $('#myForm')), nhưng bạn có thể làm cho nó chung chung hơn, như thế này:

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

Người giới thiệu: Đã cập nhật

Theo jQuery, đây là một bộ lọc để chọn tất cả các điều khiển biểu mẫu.

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

Bộ chọn đầu vào: về cơ bản chọn tất cả các điều khiển biểu mẫu.


6
$('form :input')tính đến lựa chọn, vùng văn bản và các loại đầu vào khác không? hay nó dành riêng cho thẻ đầu vào?
Val

6
Hãy sửa cho tôi nếu tôi sai, nhưng có vẻ như, phương pháp này sẽ cho biết biểu mẫu đã được thay đổi, ngay cả khi ai đó thực hiện thay đổi và sau đó "hoàn tác" thay đổi của họ, hoàn nguyên theo cách thủ công về các giá trị ban đầu trong biểu mẫu. Trong trường hợp này, biểu mẫu thực sự sẽ không thay đổi đối với dữ liệu, nhưng phương pháp này sẽ nói rằng nó đã có.
paul

1
Cảm ơn, vâng, tôi đã thử điều đó (nó được liệt kê trong một câu trả lời khác) nhưng nó không hiệu quả với tôi. Có vẻ như có một số trường hợp đặc biệt cũng đi theo phương pháp đó. Hiện đang làm việc với một plugin - github.com/codedance/jquery.AreYouSure
paul

1
Giải pháp tốt cho trường hợp này! Nhưng nếu ai đó ở đây muốn lấy trạng thái nội dung của biểu mẫu (như "IsDirty"), bạn có thể muốn làm theo giải pháp này: stackoverflow.com/a/26796840/665783
Jacob

1
@Nick Craver: Điều gì sẽ xảy ra nếu phần tử biểu mẫu nằm ngoài thẻ biểu mẫu với thuộc tính biểu mẫu là id của biểu mẫu. Tôi đã thử nghiệm trường hợp này, thật xui xẻo là nó không hoạt động.
Mahantesh

49

Nếu bạn muốn kiểm tra xem dữ liệu biểu mẫu sẽ được gửi đến máy chủ có thay đổi hay không, bạn có thể tuần tự hóa dữ liệu biểu mẫu khi tải trang và so sánh với dữ liệu biểu mẫu hiện tại:

$(function() {

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

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

});

5
Tuyệt vời, đây là giải pháp tốt nhất ở đây. Cảm ơn.
Ẩn danh

3
Tôi đã sử dụng phương pháp này một lần và nó trở nên rất chậm khi biểu mẫu trở nên lớn hơn. Đây là một phương pháp tốt cho các hình thức nhỏ, nhưng nó không phải là cách để áp dụng cho các hình thức lớn.
mkdevoogd

ý bạn là các biểu mẫu có các tệp tin trong đó?
Udi

1
Đây là tốt, nhưng nó sẽ tốt hơn nếu thay vì kiểm tra mỗi lần một điều khiển thay đổi, trực tiếp kiểm tra khi các hình thức sắp được trình
của Ruby Racer

2
Đây là tốt hơn nhiều, vì vậy bạn có thể kích hoạt các nút trở lại tàn tật, như "xóa"
EliuX

29

Một thời gian thực và giải pháp đơn giản:

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

1
Giải pháp rất tốt. Thích hợp khi bạn nhập xác thực biểu mẫu.
Bijan

1
Giải pháp tốt nhất cho tôi! Cảm ơn rất nhiều.
Ivan

2
Cân nhắc sử dụng 'input'thay vì 'keyup change'xử lý thao tác dán chuột phải, trừ khi bạn cần hỗ trợ các trình duyệt cũ hơn.
TrueWill

10

Bạn có thể sử dụng nhiều bộ chọn để đính kèm một lệnh gọi lại sự kiện thay đổi cho bất kỳ phần tử biểu mẫu nào.

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

BIÊN TẬP

Vì bạn đã đề cập rằng bạn chỉ cần cái này cho một cú nhấp chuột, bạn chỉ cần sửa đổi mã gốc của tôi thành cái này:

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

CHỈNH SỬA # 2

Được rồi, bạn có thể đặt một toàn cầu được đặt sau khi một cái gì đó đã được thay đổi như sau:

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

Nhìn vào câu hỏi cập nhật, hãy thử một cái gì đó như

$('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");
    });
});

Đối với câu hỏi ban đầu, hãy sử dụng một cái gì đó như

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

Điều này không kiểm tra <textarea>hoặc <select>các yếu tố.
Nick Craver

Sau khi bạn chỉnh sửa ... điều này có vẻ như rất nhiều công việc bổ sung và dữ liệu được di chuyển xung quanh, tất cả những gì bạn cần là booleanđặt thành true khi có thay đổi. Ngoài ra, đây vẫn không phải là biểu mẫu cụ thể, điều gì sẽ xảy ra nếu có các biểu mẫu khác trong trang?
Nick Craver

+1 đó là một điều tốt, nhưng nó cần một số công việc, ràng buộc nó để tạo thành và đặt init.
Ẩn danh

đó là những gì chính xác tôi nghĩ :) (y) của bạn làm rung chuyển
RK Sharma


2

Đây là một giải pháp thanh lịch.

Có thuộc tính ẩn cho mỗi phần tử đầu vào trên biểu mẫu mà bạn có thể sử dụng để xác định xem giá trị có bị thay đổi hay không. Mỗi loại đầu vào có tên thuộc tính riêng. Ví dụ

  • cho text/textareanó là defaultValue
  • selectmặc định Chọn
  • cho checkbox/radiodefaultChecked

Đây là ví dụ.

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();
    });
  });

};

Bây giờ chỉ cần lặp qua các biểu mẫu trên trang và bạn sẽ thấy các nút gửi bị tắt theo mặc định và chúng sẽ CHỈ được kích hoạt nếu bạn thực sự thay đổi một số giá trị đầu vào trên biểu mẫu.

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

Triển khai dưới dạng jQueryplugin tại đây https://github.com/kulbida/jmodifiable


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

Vâng, tất cả những năm sau đó tôi thậm chí không sử dụng jQuery nữa. Người quan sát và ràng buộc tất cả các cách ngay bây giờ! Mặc dù tốt cho bất kỳ ai sử dụng jQuery.
mike


1

Mở rộng câu trả lời của Udi, điều này chỉ kiểm tra khi gửi biểu mẫu, không kiểm tra mọi thay đổi đầu vào.

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

0

Đầu tiên, tôi muốn thêm một đầu vào ẩn vào biểu mẫu của bạn để theo dõi trạng thái của biểu mẫu. Sau đó, tôi sẽ sử dụng đoạn mã jQuery này để đặt giá trị của đầu vào ẩn khi một thứ gì đó trên biểu mẫu thay đổi:

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

Khi nút của bạn được nhấp, bạn có thể kiểm tra trạng thái của đầu vào ẩn của mình:

$("#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>

Ngoài câu trả lời của @ JoeD ở trên.

Nếu bạn muốn nhắm mục tiêu các trường trong một biểu mẫu cụ thể (giả sử có nhiều hơn một biểu mẫu) thay vì chỉ các trường, bạn có thể sử dụng mã sau:

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

Chỉ FYI, điều này có thể sẽ không làm những gì bạn muốn - nó nhắm mục tiêu các phần tử đầu vào của biểu mẫu "your_form_name" và tất cả các lựa chọn trong tài liệu. Ngoài ra, vì lý do hiệu suất, nó luôn luôn tốt hơn để sử dụng $ .fn.find thay vì chỉ nhắm mục tiêu selectors hậu duệ, ví dụ như là$('form').find('input,select')
DGO

@ user1167442 Còn nếu chúng ta có nhiều hơn một biểu mẫu thì sao? Ví dụ của tôi là cho một tình huống khi có nhiều hơn một biểu mẫu trong một trang.
Anjana Silva

1
Nhưng vẫn còn - ví dụ của bạn sẽ tìm thấy tất cả các phần tử đầu vào là con của biểu mẫu "your_form_name", sau đó tìm tất cả các lựa chọn xem chúng có phải là con của "your_form_name" hay không. Ví dụ của bạn sẽ không hoạt động cho nhiều biểu mẫu, trừ khi bạn chỉ nhắm mục tiêu các lựa chọn của các biểu mẫu đó. Ngoài ra, nếu bạn đang đề cập đến phần hiệu suất, tốt hơn hết là bạn nên sử dụng $.fn.find- nhanh hơn thậm chí $.fn.filter- để tham chiếu đến trẻ em hơn là sử dụng bộ chọn con cháu. vaughnroyko.com/the-real-scoop-on-jquery-find-performance
dgo

1
@ user1167442, bạn hoàn toàn đúng. Tôi đã bỏ lỡ thực tế là lựa chọn đang được nhắm mục tiêu bất kể bạn đang ở dạng nào. Tôi đã sửa điều đó. Cảm ơn bạn rất nhiều vì đã chỉ ra. Chúc mừng!
Anjana Silva

0

Thử đi:

<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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.