jQueryでフォームの変更をどのように処理しますか?


82

jQueryで、フォームの要素のいずれかが変更されたかどうかをテストする簡単な方法はありますか?

編集:私は私がチェックする必要があるだけであることを追加する必要がありましたclick()イベント。

編集:申し訳ありませんが、私は本当にもっと具体的にすべきでした!フォームがあり、次のボタンがあるとします。

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

ロードされてからフォームが変更されたかどうかをテストするにはどうすればよいですか?


ページに含まれている他のスクリプトのアクションを意味しますか、それともユーザーがテキストを入力するか、ラジオ/チェックボックスをクリックするとすぐに意味しますか?
FelipeAls 2010年

click()イベントをチェックするだけでよいことを追加する必要があります
マイク2010年

回答:


141

あなたはこれを行うことができます:

$("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–
paul

1
この場合の良い解決策です!しかし、ここの誰かがフォームのコンテンツの状態(「IsDirty」など)を取得したい場合は、次の解決策に従うことをお勧めします:stackoverflow.com/a/26796840/665783
Jacob

1
@Nick Craver:フォーム要素がフォームタグの外側にあり、フォーム属性がフォームのIDである場合はどうなりますか。私はケースをテストしました、それが機能していない不運。
マハンテシュ

50

サーバーに送信されるフォームデータが変更されているかどうかを確認する場合は、ページの読み込み時にフォームデータをシリアル化して、現在のフォームデータと比較できます。

$(function() {

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

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

});

5
すばらしい、これがここでの最良の解決策です。ありがとう。
匿名

3
私は一度この方法を使用しましたが、フォームが大きくなると非常に遅くなりました。これは小さなフォームには適した方法ですが、大きなフォームには適していません。
mkdevoogd 2013

ファイルが含まれているフォームを意味しますか?
Udi 2013

1
これは良いことですが、コントロールが変更されるたびにチェックするのではなく、フォームが送信されようとしているときに直接チェックする方がよいでしょう
Ruby Racer

2
これははるかに優れているため、「削除」のようにボタンを無効に戻すことができます
EliuX 2015

31

リアルタイムでシンプルなソリューション:

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

1
非常に良い解決策。フォームの検証を入力するときに適しています。
Bijan 2014

1
私にとって最良の解決策!どうもありがとう。
Ivan

2
古いブラウザをサポートする必要がない限り、右マウス貼り付けを処理する'input'代わりに'keyup change'を使用することを検討してください。
TrueWill 2016

10

複数のセレクターを使用して、任意のフォーム要素の変更イベントにコールバックをアタッチできます。

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

編集

クリックするだけでこれが必要だとおっしゃっていたので、元のコードを次のように変更するだけです。

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

編集#2

OK、次のように何かが変更されたときに設定されるグローバルを設定できます。

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>要素をチェックしません。
NickCraver

編集後...これは多くの余分な作業とデータが移動しているように見えます。必要なのはboolean、変更が発生したときにtrueに設定することだけです。また、これはまだフォーム固有ではありません。ページに他のフォームがあった場合はどうなりますか?
NickCraver

+1は良いものですが、いくつかの作業が必要です。フォームにバインドしてinitを設定します。
匿名

それはまさに私が思ったものです:)(y)あなたの揺れ
RK Sharma 2015


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

jQueryプラグインとしての実装はこちらhttps://github.com/kulbida/jmodizable


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複数のフォームがある場合はどうですか?私の例は、1つのページに複数のフォームがある状況です。
AnjanaSilva18年

1
しかし、それでも-あなたの例では、「your_form_name」フォームの子であるすべての入力要素を検索し、次にそれらが「your_form_name」の子であるか、任意のフォームであるかをすべて選択します。これらのフォームの選択のみを対象としている場合を除き、例は複数のフォームでは機能しません。また、パフォーマンスピースを参照している場合は、子孫セレクターを使用するよりも、子を参照$.fn.findするために(偶数よりも速く)使用することをお勧めします$.fn.filtervaughnroyko.com/the-real-scoop-on-jquery-find-performance
DGO

1
@ user1167442、あなたは絶対に正しいです。どのフォームを使用していても、selectがターゲットになっているという事実を見逃しました。修正しました。ご指摘ありがとうございます。乾杯!
AnjanaSilva18年

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>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.