jQuery에서 양식 변경을 어떻게 처리합니까?


81

jQuery에서 양식의 요소가 변경되었는지 테스트하는 간단한 방법이 있습니까?

편집 :click() 이벤트 만 확인하면된다고 추가해야합니다 .

편집 : 정말 더 구체적이어야 미안합니다! 양식이 있고 다음과 같은 버튼이 있다고 가정합니다.

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

양식이로드 된 후 변경되었는지 어떻게 테스트합니까?


페이지에 포함 된 다른 스크립트의 동작을 의미합니까, 아니면 사용자가 텍스트를 입력하거나 라디오 / 체크 박스를 클릭하자마자 의미합니까?
FelipeAls 2010-06-11

click () 이벤트 만 확인하면된다고 추가 했어야합니다
mike

답변:


140

다음과 같이 할 수 있습니다.

$("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
내가 틀렸다면 정정 해주세요.이 방법은 누군가가 변경 한 다음 변경을 "취소"하여 양식의 원래 값으로 수동으로 되돌려도 양식이 변경되었다고 말합니다. 이 경우 형식은 데이터와 관련하여 실제로 변경되지 않았지만이 방법은 변경되었다고 말할 수 있습니다.
paul

1
고마워, 그래도 시도했지만 (다른 답변에 나열되어 있음) 저에게 효과가 없었습니다. 그 방법을 넘어서는 특별한 경우가있는 것 같습니다. 현재 플러그인 작업 - github.com/codedance/jquery.AreYouSure

1
이 경우에 좋은 솔루션입니다! 그러나 여기에있는 누군가가 양식의 콘텐츠 상태 (예 : "IsDirty")를 얻으려면 다음 솔루션을 따르십시오. stackoverflow.com/a/26796840/665783
Jacob

1
@Nick Craver : 양식 요소가 양식의 ID로 양식 속성이있는 양식 태그 외부에 있으면 어떻게 될까요? 나는 케이스를 테스트했지만 운이 좋지 않습니다.
Mahantesh

49

서버로 보낼 양식 데이터가 변경되었는지 확인하려면 페이지로드시 양식 데이터를 직렬화하고 현재 양식 데이터와 비교할 수 있습니다.

$(function() {

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

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

});

5
훌륭합니다. 이것이 최고의 솔루션입니다. 감사.
Anonymous

3
이 방법을 한 번 사용했는데 형태가 커지면 매우 느려졌습니다. 이것은 작은 양식에는 좋은 방법이지만 큰 양식에는 적합하지 않습니다.
mkdevoogd 2013

파일이있는 양식을 의미합니까?
Udi

1
이것은 좋지만 컨트롤이 변경 될 때마다 확인하는 대신 양식이 제출 될시기를 직접 확인하는 것이 더 좋을 것입니다
Ruby Racer

2
이 방법이 훨씬 낫기 때문에 "삭제"와 같이 버튼을 비활성화 상태로 되돌릴 수 있습니다.
EliuX

29

실시간 및 간단한 솔루션 :

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

1
아주 좋은 솔루션입니다. 양식 유효성 검사를 입력 할 때 적합합니다.
Bijan 2014

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>요소를 확인하지 않습니다 .
Nick Craver

편집 후 ... 이것은 많은 추가 작업과 데이터가 이동되는 것처럼 보이며 boolean변경이 발생할 때 필요한 것은 true 로 설정하는 것뿐입니다. 또한 이것은 여전히 ​​양식별로 다르지 않습니다. 페이지에 다른 양식이 있으면 어떻게됩니까?
Nick Craver

+1은 좋지만 약간의 작업이 필요하고 바인딩하여 형성하고 초기화합니다.
Anonymous

그 :) 내가 생각 정확히 무엇 (Y) 당신의 누 볐어
RK 샤르마


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를 사용하는 모든 사람에게 좋습니다.
mike


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 양식이 두 개 이상이면 어떻습니까? 내 예는 단일 페이지에 둘 이상의 양식이있는 상황입니다.
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, 당신은 절대적으로 옳습니다. 나는 당신이 어떤 형태에 있든 상관없이 select가 표적이된다는 사실을 놓쳤다. 나는 그것을 수정했다. 지적 해 주셔서 대단히 감사합니다. 건배!
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>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.