JQuery'de bir form değişikliğini nasıl işlersiniz?


82

JQuery'de, bir formun HERHANGİ BİRİNİN değişip değişmediğini test etmenin basit bir yolu var mı?

DÜZENLEME: Sadece bir click()olayı kontrol etmem gerektiğini eklemeliydim .

DÜZENLEME: Üzgünüm, gerçekten daha spesifik olmalıydım! Bir formum olduğunu ve aşağıdakileri içeren bir düğmem olduğunu varsayalım:

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

Form yüklendikten sonra değişip değişmediğini nasıl test ederim?


Sayfada bulunan başka bir komut dosyasının eylemi ile mi yoksa kullanıcı bir metin yazdığında veya bir radyo / onay kutusunu tıkladığında mı kastediyorsunuz?
FelipeAls

Sadece bir click () etkinliğini kontrol etmem gerektiğini eklemeliydim
mike

Yanıtlar:


141

Bunu yapabilirsiniz:

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

Bu kuleleri changebunlardan herhangi kullandığı değiştirirseniz, formda girişlere olay işleyicisi .data()bir ayarlama changeddeğerini trueo zaman sadece bir tıklama ile bu değer için kontrol, bu varsayar #mybutton(sadece yerini ise forma içindeyse $(this).closest('form')ile $('#myForm'),) ancak bunu şu şekilde daha genel hale getirebilirsiniz:

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

Referanslar: Güncellendi

JQuery'ye göre bu, tüm form kontrollerini seçmek için bir filtredir.

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

: İnput seçici temel olarak tüm form kontrollerini seçer.


6
Does $('form :input')seçme, textarea ve diğer giriş türleri için hesap? yoksa giriş etiketine özel mi?
Val

6
Yanılıyorsam düzeltin, ama öyle görünüyor ki, bu yöntem, birisi bir değişiklik yapsa ve sonra değişikliğini "geri alsa", formdaki orijinal değerlere manuel olarak geri dönse bile formun değiştirildiğini söyleyecektir. Bu durumda form verilere göre gerçekten değişmezdi, ancak bu yöntem değişti diyebilirdi.
paul

1
Teşekkürler, evet bunu denedim (başka bir cevapta listelenmiştir) ama benim için işe yaramadı. Bu yöntemi aşan bazı özel durumlar da var gibi görünüyor. Şu anda bir eklentiyle çalışıyor - github.com/codedance/jquery.AreYouSure
paul

1
Bu durum için iyi bir çözüm! Ancak buradaki biri formun içeriğinin durumunu öğrenmek istiyorsa ("IsDirty" gibi), şu çözümü takip etmek isteyebilirsiniz: stackoverflow.com/a/26796840/665783
Jacob

1
@Nick Craver: Ya form öğesi, formun id olarak form özniteliğine sahip form etiketinin dışındaysa. Davayı test ettim, şanssızlık çalışmıyor.
Mahantesh

50

Sunucuya gönderilecek olan form verilerinin değişip değişmediğini kontrol etmek isterseniz, sayfa yüklemede form verilerini seri hale getirebilir ve mevcut form verileriyle karşılaştırabilirsiniz:

$(function() {

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

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

});

5
Mükemmel, buradaki en iyi çözüm bu. Teşekkürler.
Anonim

3
Bu yöntemi bir kez kullandım ve form büyüdüğünde çok yavaşladı. Bu, küçük formlar için iyi bir yöntemdir, ancak büyük formlar için doğru yol değildir.
mkdevoogd

İçinde dosyalar olan formları mı kastediyorsun?
Udi

1
Bu iyi, ancak her kontrol değişikliğinde kontrol etmek yerine, formun ne zaman gönderileceğini doğrudan kontrol
Ruby Racer

2
Bu çok daha iyi, bu nedenle düğmeleri "sil" gibi devre dışı
bırakabilirsiniz

31

Gerçek zamanlı ve basit bir çözüm:

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

1
Çok güzel bir çözüm. Form doğrulama yazarken uygun.
Bijan

1
Benim için en iyi çözüm! Çok teşekkürler.
Ivan

2
Daha eski tarayıcıları desteklemeniz gerekmedikçe, sağ fare ile yapıştırmayı işlemek 'input'yerine kullanmayı düşünün 'keyup change'.
TrueWill

10

Herhangi bir form öğesi için change olayına bir geri çağrı eklemek için birden çok seçici kullanabilirsiniz.

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

DÜZENLE

Buna yalnızca bir tıklama için ihtiyacınız olduğunu belirttiğinizden, orijinal kodumu buna göre değiştirebilirsiniz:

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

DÜZENLE # 2

Tamam, aşağıdaki gibi bir şey değiştiğinde ayarlanmış bir global ayarlayabilirsiniz:

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

Güncellenen soruya bakınca şunun gibi bir şey deneyin:

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

Orijinal soru için aşağıdaki gibi bir şey kullanın

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

Bu kontrol <textarea>veya <select>unsurlar değil .
Nick Craver

Düzenlemenizden sonra ... bu, çok fazla ek çalışma ve verilerin taşınması gibi görünüyor, tek ihtiyacınız booleanolan şey, bir değişiklik olduğunda doğruya ayarlanmasıdır. Ayrıca, bu yine de forma özgü değil, ya sayfada başka formlar varsa?
Nick Craver

+1 bu iyi bir şey, ancak biraz çalışmaya ihtiyacı var, onu oluşturmak ve başlatmak için bağlayın.
Anonim

tam olarak düşündüğüm buydu :) (y) harikasınız
RK Sharma


2

İşte zarif bir çözüm.

Formda, değerin değiştirilip değiştirilmediğini belirlemek için kullanabileceğiniz her giriş öğesi için gizli özellik vardır. Her girdi türünün kendi özellik adı vardır. Örneğin

  • için text/textareabu kadar defaultValue
  • için selectbu kadar defaultSelect
  • için checkbox/radio's defaultChecked

İşte örnek.

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

};

Şimdi sadece sayfadaki formlar arasında döngü yapın ve gönderme düğmelerinin varsayılan olarak devre dışı olduğunu görmelisiniz ve YALNIZCA formdaki bazı giriş değerlerini gerçekten değiştirirseniz bunlar etkinleştirilecektir.

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

Bir şekilde uygulanması jQueryeklentisi burada 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();
      ...
   }
}

Evet bunca yıl sonra artık jQuery kullanmıyorum. Gözlemciler ve bağlar artık her yerde! JQuery kullanan herkes için güzel olsa da.
mike


1

Udi'nin cevabını genişleterek, bu her giriş değişikliğini değil, yalnızca form gönderimini kontrol eder.

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

0

İlk olarak, formun durumunu izlemek için formunuza gizli bir giriş eklerim. Ardından, formdaki bir şey değiştiğinde gizli girişin değerini ayarlamak için bu jQuery snippet'ini kullanırdım:

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

Düğmenize tıklandığında, gizli girişinizin durumunu kontrol edebilirsiniz:

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

Yukarıdaki @ JoeD cevabına ek olarak.

Belirli bir formdaki alanları hedeflemek istiyorsanız (birden fazla form olduğu varsayılarak), yalnızca alanlardan çok, aşağıdaki kodu kullanabilirsiniz:

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

Bilginize, bu muhtemelen istediğiniz şeyi yapmaz - "form_adınız" formunun giriş öğelerini ve belgedeki tüm seçimleri hedefler. Ayrıca, performansla ilgili nedenlerden ötürü, sadece alt seçicileri hedeflemek yerine $ .fn.find kullanmak her zaman daha iyidir, örneğin$('form').find('input,select')
dgo

@ user1167442 Birden fazla formumuz olsa nasıl olur? Örneğim, tek bir sayfada birden fazla formun olduğu bir durum içindir.
Anjana Silva

1
Ancak yine de - örneğiniz "form_adınız" formunun alt öğeleri olan tüm girdi öğelerini bulacak ve sonra bunların "form_adınız" ın alt öğesi veya herhangi bir formun alt öğesi olup olmadıklarını tüm seçimleri bulacaktır. Yalnızca bu formların seçimlerini hedeflemediğiniz sürece, örneğiniz birden çok form için çalışmayacaktır. Performans parçasına atıfta Ayrıca, eğer, her zaman daha iyi kullanmaktır $.fn.findhızlı hatta daha - $.fn.filter- Referans çocuklara ziyade soyundan seçiciler kullanmak yerine. vaughnroyko.com/the-real-scoop-on-jquery-find-performance
dgo

1
@ user1167442, kesinlikle haklısınız. Hangi formda olursanız olun, Select'in hedeflendiği gerçeğini gözden kaçırdım. Bunu düzelttim. İşaret ettiğiniz için çok teşekkür ederim. Şerefe!
Anjana Silva

0

Bunu dene:

<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>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.