programing

jQuery - 숨겨진 입력 필드에서 값 변경을 탐지합니다.

itmemos 2023. 5. 17. 22:30
반응형

jQuery - 숨겨진 입력 필드에서 값 변경을 탐지합니다.

AJAX 응답을 통해 값이 업데이트되는 숨겨진 텍스트 필드가 있습니다.

<input type="hidden" value="" name="userid" id="useid" />

이 값이 변경되면 AJAX 요청을 하고 싶습니다.변화를 감지하는 방법에 대해 조언해 줄 수 있는 사람이 있습니까?

다음 코드가 있지만 값을 찾는 방법을 모르겠습니다.

$('#userid').change( function() {  
    alert('Change!'); 
}) 

그래서 이것은 너무 늦었지만, 저는 이 실마리를 발견한 사람들에게 유용하게 쓰일 수 있는 답을 발견했습니다.

숨겨진 요소에 대한 값 변경은 .change() 이벤트를 자동으로 실행하지 않습니다.따라서 해당 값을 설정하는 곳이 어디든 jQuery에 해당 값을 트리거하도록 지시해야 합니다.

function setUserID(myValue) {
     $('#userid').val(myValue)
                 .trigger('change');
}

일단 그렇게 되면,

$('#userid').change(function(){
      //fire your ajax call  
})

예상대로 작동해야 합니다.

숨겨진 입력이 변경 시 "변경" 이벤트를 트리거하지 않기 때문에 MutationObserver를 사용하여 이 이벤트를 트리거했습니다.

(가끔 숨겨진 입력 값 변경은 수정할 수 없는 다른 스크립트에 의해 수행됩니다.)

IE10 이하에서는 작동하지 않습니다.

MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var trackChange = function(element) {
  var observer = new MutationObserver(function(mutations, observer) {
    if(mutations[0].attributeName == "value") {
        $(element).trigger("change");
    }
  });
  observer.observe(element, {
    attributes: true
  });
}

// Just pass an element to the function to start tracking
trackChange( $("input[name=foo]")[0] );

아래 기능을 사용하시면 됩니다. 유형 요소를 변경할 수도 있습니다.

 $("input[type=hidden]").bind("change", function() {
       alert($(this).val()); 
 });

숨겨진 요소에 대한 값 변경은 .change() 이벤트를 자동으로 실행하지 않습니다.따라서 해당 값을 설정하는 곳이 어디든 jQuery에 해당 값을 트리거하도록 지시해야 합니다.

HTML

 <div id="message"></div>
<input type="hidden" id="testChange" value="0"  />    

자바스크립트

var $message = $('#message');
var $testChange = $('#testChange');
var i = 1;

function updateChange() {
    $message.html($message.html() + '<p>Changed to ' + $testChange.val() + '</p>');
}

$testChange.on('change', updateChange);

setInterval(function() {
    $testChange.val(++i).trigger('change');; 
    console.log("value changed" +$testChange.val());
}, 3000);

updateChange();

예상대로 작동해야 합니다.

http://jsfiddle.net/7CM6k/3/

$('#userid').change(function(){
  //fire your ajax call  
});

$('#userid').val(10).change();

Viktar의 답변을 바탕으로, 입력 요소의 값이 변경될 때마다 후속 변경 이벤트가 발생하도록 지정된 숨겨진 입력 요소에 대해 한 번 호출할 수 있는 구현이 있습니다.

/**
 * Modifies the provided hidden input so value changes to trigger events.
 *
 * After this method is called, any changes to the 'value' property of the
 * specified input will trigger a 'change' event, just like would happen
 * if the input was a text field.
 *
 * As explained in the following SO post, hidden inputs don't normally
 * trigger on-change events because the 'blur' event is responsible for
 * triggering a change event, and hidden inputs aren't focusable by virtue
 * of being hidden elements:
 * https://stackoverflow.com/a/17695525/4342230
 *
 * @param {HTMLInputElement} inputElement
 *   The DOM element for the hidden input element.
 */
function setupHiddenInputChangeListener(inputElement) {
  const propertyName = 'value';

  const {get: originalGetter, set: originalSetter} =
    findPropertyDescriptor(inputElement, propertyName);

  // We wrap this in a function factory to bind the getter and setter values
  // so later callbacks refer to the correct object, in case we use this
  // method on more than one hidden input element.
  const newPropertyDescriptor = ((_originalGetter, _originalSetter) => {
    return {
      set: function(value) {
        const currentValue = originalGetter.call(inputElement);

        // Delegate the call to the original property setter
        _originalSetter.call(inputElement, value);

        // Only fire change if the value actually changed.
        if (currentValue !== value) {
          inputElement.dispatchEvent(new Event('change'));
        }
      },

      get: function() {
        // Delegate the call to the original property getter
        return _originalGetter.call(inputElement);
      }
    }
  })(originalGetter, originalSetter);

  Object.defineProperty(inputElement, propertyName, newPropertyDescriptor);
};

/**
 * Search the inheritance tree of an object for a property descriptor.
 *
 * The property descriptor defined nearest in the inheritance hierarchy to
 * the class of the given object is returned first.
 *
 * Credit for this approach:
 * https://stackoverflow.com/a/38802602/4342230
 *
 * @param {Object} object
 * @param {String} propertyName
 *   The name of the property for which a descriptor is desired.
 *
 * @returns {PropertyDescriptor, null}
 */
function findPropertyDescriptor(object, propertyName) {
  if (object === null) {
    return null;
  }

  if (object.hasOwnProperty(propertyName)) {
    return Object.getOwnPropertyDescriptor(object, propertyName);
  }
  else {
    const parentClass = Object.getPrototypeOf(object);

    return findPropertyDescriptor(parentClass, propertyName);
  }
}

다음과 같이 준비된 문서에서 호출:

$(document).ready(function() {
  setupHiddenInputChangeListener($('myinput')[0]);
});

사용할 수 있습니다.Object.defineProperty()입력 요소의 '값' 속성을 재정의하고 변경하는 동안 모든 작업을 수행합니다.

Object.defineProperty()속성에 대한 게터 및 세터를 정의하여 속성을 제어할 수 있습니다.

replaceWithWrapper($("#hid1")[0], "value", function(obj, property, value) { 
  console.log("new value:", value)
});

function replaceWithWrapper(obj, property, callback) {
  Object.defineProperty(obj, property, new function() {
    var _value = obj[property];
    return {
      set: function(value) {
        _value = value;
        callback(obj, property, value)
      },
      get: function() {
        return _value;
      }
    }
  });
}

$("#hid1").val(4);

https://jsfiddle.net/bvvmhvfk/

Vikars 답변으로 시작했지만 HTML 형식으로 사용된 숨겨진 양식 필드가 마지막 변경사항을 제출하지 않았다는 것도 알게 되었습니다.나중에 Thomas의 답변을 발견했기 때문에 다음 솔루션에 둘 다 결합했습니다. 이 솔루션은 제출할 때 숨겨진 양식 필드에도 잘 작동하는 것 같습니다.

   function replaceWithWrapper(selector, property, callback) {
      function findDescriptor(obj, prop){
         if (obj != null){
            return Object.hasOwnProperty.call(obj, prop)?
               Object.getOwnPropertyDescriptor(obj, prop):
               findDescriptor(Object.getPrototypeOf(obj), prop);
         }
      }

      jQuery(selector).each(function(idx, obj) {
         var {get, set} = findDescriptor(obj, property);

         Object.defineProperty(obj, property, {
            configurable: true,
            enumerable: true,

            get() { //overwrite getter
               var v = get.call(this);  //call the original getter
               //console.log("get '+property+':", v, this);
               return v;
            },
            
            set(v) { //same for setter
               //console.log("set '+property+':", v, this);
               set.call(this, v);
               callback(obj, property, v)
            }
         });
      });
   }

   replaceWithWrapper('#myhiddenfield', 'value', function() {
      console.log('myhiddenfield value changed!');
   });

다음 예제에서는 숨겨진 초안 필드가 값을 변경할 때마다 초안 필드 값을 반환합니다(크롬 브라우저).

var h = document.querySelectorAll('input[type="hidden"][name="draft"]')[0];
//or jquery.....
//var h = $('input[type="hidden"][name="draft"]')[0];

observeDOM(h, 'n', function(draftValue){ 
  console.log('dom changed draftValue:'+draftValue);
});


var observeDOM = (function(){
var MutationObserver = window.MutationObserver || 
window.WebKitMutationObserver;

  return function(obj, thistime, callback){
    if(typeof obj === 'undefined'){
      console.log('obj is undefined');
      return;
    }

    if( MutationObserver ){

        // define a new observer
        var obs = new MutationObserver(function(mutations, observer){

            if( mutations[0].addedNodes.length || mutations[0].removedNodes.length ){

               callback('pass other observations back...');

            }else if(mutations[0].attributeName == "value" ){

               // use callback to pass back value of hidden form field                            
               callback( obj.value );

            }

        });

        // have the observer observe obj for changes in children
        // note 'attributes:true' else we can't read the input attribute value
        obs.observe( obj, { childList:true, subtree:true, attributes:true  });

       }
  };
})();

이 스레드는 3년이 되었지만, 제 솔루션은 다음과 같습니다.

$(function ()
{
    keep_fields_uptodate();
});

function keep_fields_uptodate()
{
    // Keep all fields up to date!
    var $inputDate = $("input[type='date']");
    $inputDate.blur(function(event)
    {
        $("input").trigger("change");
    });
}

언급URL : https://stackoverflow.com/questions/6533087/jquery-detect-value-change-on-hidden-input-field

반응형