Як ви обробляєте зміну форми в jQuery?


82

У jQuery чи існує простий спосіб перевірити, чи змінився БУДЬ-який елемент форми?

EDIT: Я повинен був додати, що мені потрібно лише перевірити click()подію.

РЕДАГУВАТИ: Вибачте, я справді мав бути більш конкретним! Скажімо, у мене є форма, і у мене є кнопка із таким:

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

Як я можу перевірити, чи змінилася форма після завантаження?


Ви маєте на увазі під дією якийсь інший сценарій, включений на сторінку, або як тільки користувач набрав якийсь текст або натиснув радіо / прапорець?
FelipeAls

Я повинен був додати, що мені потрібно лише перевірити подію click ()
mike

Відповіді:


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')враховуються вибрані, текстові області та інші типи введення? чи це специфічно для вхідного тегу?
Валь

6
Виправте мене, якщо я помиляюся, але, схоже, цей метод скаже, що форму було змінено, навіть якщо хтось внесе зміни, а потім "скасує" їх зміни, повернувшись вручну до початкових значень у формі. У цьому випадку форма дійсно не змінилася б щодо даних, проте цей метод сказав би, що так і було.
Пол

1
Дякую, так, я спробував це (це вказано в іншій відповіді), але мені це не вдалося. Здається, що є деякі особливі випадки, які також відхиляють цей метод. В даний час працює з плагіном - github.com/codedance/jquery.AreYouSure
Пол

1
Хороше рішення для цієї справи! Але якщо хтось тут хоче отримати стан вмісту форми (наприклад, "IsDirty"), ви можете дотримуватися цього рішення: stackoverflow.com/a/26796840/665783
Яків,

1
@Nick Craver: Що робити, якщо елемент форми знаходиться поза тегом форми з атрибутом форми як ідентифікатором форми. Я перевірив справу, нещастя не працює.
Махантеш,

50

Якщо ви хочете перевірити, чи змінилися дані форми, оскільки вони будуть надіслані на сервер, ви можете серіалізувати дані форми при завантаженні сторінки та порівняти їх із поточними даними форми:

$(function() {

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

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

});

5
Чудово, це найкраще рішення тут. Дякую.
Анонім

3
Я використав цей метод один раз, і він став дуже повільним, коли форма стала більшою. Це хороший метод для малих форм, але це не шлях для великих форм.
mkdevoogd

ви маєте на увазі форми з файлами в них?
Уді

1
Це добре, але було б краще, щоб замість перевірки кожного разу, коли елемент керування змінюється, безпосередньо перевіряти, коли форма має бути подана
Ruby Racer

2
Це набагато краще, тому ви можете повернути кнопки до вимкнених, наприклад "видалити"
EliuX

31

Просте рішення в режимі реального часу:

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

1
Дуже хороше рішення. Підходить для перевірки форми під час набору тексту.
Bijan

1
Найкраще рішення для мене! Дуже дякую.
Іван

2
Подумайте про використання 'input'замість того, 'keyup change'щоб обробляти вставку правою кнопкою миші, якщо вам не потрібно підтримувати старіші браузери.
TrueWill

10

Ви можете використовувати кілька селекторів, щоб приєднати зворотний виклик до події зміни для будь-якого елемента форми.

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

РЕДАГУВАТИ

Оскільки ви згадали, що це потрібно лише для клацання, ви можете просто змінити мій оригінальний код до цього:

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

EDIT # 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.
Анонім

це саме те, що я думав :) (у) твої розхитані
РК Шарма


2

Ось елегантне рішення.

Для кожного вхідного елемента форми є прихована властивість, за допомогою якої можна визначити, чи було змінено значення. Кожен тип введення має свою власну назву властивості. Наприклад

  • оскільки text/textareaце defaultValue
  • для selectце defaultSelect
  • оскільки checkbox/radioце за замовчуванням перевірено

Ось приклад.

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/jmodifiable


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

Так, усі ці роки потому я навіть більше не використовую jQuery. Спостерігачі та прив'язки до кінця! Хороший, хоча для тих, хто використовує jQuery.
mike


1

Розширюючи відповідь Уді, це перевіряє лише подання форми, а не кожну зміну вводу.

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

Тільки FYI, це, мабуть, не буде робити те, що ви хочете - воно націлено на вхідні елементи форми "your_form_name" і всі виділяє в документі. Крім того, з міркувань продуктивності завжди краще використовувати $ .fn.find, а не просто орієнтуватися на нащадкових селекторів, наприклад$('form').find('input,select')
dgo

@ user1167442 Як щодо того, якщо ми маємо більше однієї форми? Мій приклад для ситуації, коли на одній сторінці є більше однієї форми.
Anjana Silva

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

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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.