Как вы обрабатываете изменение формы в 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!");
});
Pez Cuckow
источник
Это не проверяет элементы <textarea>или <select>.
Ник Крейвер
После вашего редактирования ... похоже, что это много дополнительной работы и перемещаемых данных, все, что вам нужно, это booleanустановить значение true, когда происходит изменение. Кроме того, это все еще не зависит от формы, что, если бы на странице были другие формы?
Ник Крейвер
+1 это хороший, но нужно немного доработать, привязать его к форме и установить init.
Anonymous
это именно то, о чем я подумал :) (у) твое потрясение
РК Шарма
2
$('form :input').change(function() {
    // Something has changed
});
Голосовать
источник
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...
    }
});
JMP
источник
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>
Винод Сарасват
источник