Как вы обрабатываете изменение формы в jQuery?


82

В jQuery есть ли простой способ проверить, изменились ли ЛЮБЫЕ элементы формы?

РЕДАКТИРОВАТЬ: я должен был добавить, что мне нужно только проверить click()событие.

РЕДАКТИРОВАТЬ: Извините, я действительно должен был быть более конкретным! Скажем, у меня есть форма и кнопка со следующим:

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

Как мне проверить, изменилась ли форма с момента загрузки?


Вы имеете в виду действие какого-либо другого скрипта, включенного на страницу, или как только пользователь набрал текст или щелкнул переключатель / флажок?
— FelipeAls

Я должен был добавить, что мне нужно только проверить событие click ()
— Майк,

Ответы:


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
Отлично, это лучшее решение. Благодарю.
— Anonymous

3
Я использовал этот метод однажды, и он стал очень медленным, когда форма стала больше. Это хороший метод для малых форм, но не для больших.
— mkdevoogd

вы имеете в виду формы с файлами в них?
— Уди

1
Это хорошо, но было бы лучше, если бы вместо проверки каждый раз при изменении элемента управления напрямую проверяли, когда форма собирается быть отправлена
— Ruby Racer

2
Это намного лучше, так что вы можете переключать кнопки обратно в отключенное состояние, например, «удалить»
— EliuX

31

Простое решение в реальном времени:

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

1
Очень хорошее решение. Подходит для проверки формы по мере ввода.
— Биджан

1
Лучшее решение для меня! Большое спасибо.
— Иван

2
Рассмотрите возможность использования 'input'вместо 'keyup change'обработки вставки правой кнопкой мыши, если вам не нужна поддержка старых браузеров.
— TrueWill

10

Вы можете использовать несколько селекторов, чтобы присоединить обратный вызов к событию изменения для любого элемента формы.

$("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.
— Anonymous

это именно то, о чем я подумал :) (у) твое потрясение
— РК Шарма


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


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

Да, все эти годы спустя я даже не использую jQuery. Наблюдатели и привязки теперь полностью! Хотя это приятно для всех, кто использует jQuery.
— Майк


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

К вашему сведению, это, вероятно, не будет делать то, что вы хотите - оно нацелено на элементы ввода формы «your_form_name» и все выборки в документе. Кроме того, по соображениям производительности всегда лучше использовать $ .fn.find, а не просто настраивать таргетинг на $('form').find('input,select')
— дочерние

@ user1167442 А если у нас более одной формы? Мой пример предназначен для ситуации, когда на одной странице находится более одной формы.
— Анджана Сильва

1
Но все же - ваш пример найдет все элементы ввода, которые являются дочерними элементами формы your_form_name, а затем найдет все выбранные элементы, являются ли они дочерними элементами формы your_form_name или любой другой формы. Ваш пример не будет работать для нескольких форм, если вы не нацеливаетесь только на выборку этих форм. Кроме того, если вы говорите о производительности, всегда лучше использовать $.fn.find- быстрее, чем даже $.fn.filter- для ссылки на дочерние элементы, а не использовать дочерние селекторы. vaughnroyko.com/the-real-scoop-on-jquery-find-performance
— dgo

1
@ user1167442, вы абсолютно правы. Я упустил тот факт, что select является целью независимо от того, в какой форме вы находитесь. Я исправил это. Большое спасибо за указание. Ура!
— Анджана Сильва

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.