【问题标题】:jQuery - Detect value change on hidden input fieldjQuery - 检测隐藏输入字段的值变化
【发布时间】:2011-09-25 20:39:12
【问题描述】:

我有一个隐藏的文本字段,其值通过 AJAX 响应更新。

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

当这个值改变时,我想触发一个 AJAX 请求。谁能建议如何检测变化?

我有以下代码,但不知道如何查找值:

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

【问题讨论】:

  • 如果它通过 ajax 响应更新,为什么不在响应的成功函数中触发新的 ajax 请求?
  • $('#userid').val() 会给你价值,如果这就是你要问的
  • 更新:当隐藏字段的值被更新时,现在会触发一个更改事件。

标签: jquery event-handling field onchange hidden


【解决方案1】:

所以这已经很晚了,但我发现了一个答案,以防万一它对遇到此线程的任何人有用。

对隐藏元素的值更改不会自动触发 .change() 事件。因此,无论您在哪里设置该值,您还必须告诉 jQuery 触发它。

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

既然如此,

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

应该按预期工作。

【讨论】:

  • 使用.trigger() 是否比仅调用change() 更好?
  • 它有效,但它似乎触发了两次更改事件!。就像如果我输入这段代码,它会触发两次,如果我删除代码,则不会触发 w/e。!!
  • 要使其行为与change 事件相同,您应该在setUserID() 中添加代码以检查该值是否真的发生了变化。 if ($('#userid').val() != myVaule) { // set val() and trigger change }
  • 如果您试图捕捉通过 javascript 更改的“更改”事件,这将特别有用,否则 .change(handler) 或 .on 无法捕获 javascript 所做的更改(“改变”,处理程序)
  • 所以如果我无法控制更改隐藏字段值的函数(即无法触发触发器),此解决方案将不起作用,对吧?
【解决方案2】:

由于隐藏输入不会在更改时触发“更改”事件,因此我使用 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] );

【讨论】:

  • AFAIK 突变观察者也不会因文本字段内的更改而被触发(无论是否隐藏)
  • 效果很好! @OleAlbers - OP 询问了input[type=hidden]
  • 我将它与使用 jquery 的 map 命令检索隐藏输入字段值集合的函数结合使用。非常感谢@lulalala!
  • 简单易懂。此解决方案与“更改值时必须触发事件”解决方案相反,它不依赖于程序员在值更改时访问代码,只要您不这样做,它就会变得更有用不必支持早于 IE11 的版本。它对我很有用。谢谢
  • 很好的解决方案!谢谢!出于某种原因,trigger('change') 对我不起作用,所以我创建了一个 CustomEvent,注册了它,然后element.dispatchEvent(myCustomEvent)
【解决方案3】:

你可以简单地使用下面的函数,你也可以改变类型元素。

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

对隐藏元素的值更改不会自动触发 .change() 事件。所以,无论你在哪里设置这个值,你也必须告诉 jQuery 来触发它。

HTML

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

JAVASCRIPT

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/

【讨论】:

  • 不适合我...无论如何,如何将值粘贴到隐藏字段中? ://
  • 嘿,谢谢,粘贴不应该在那里,但是更改可以检测到隐藏字段更改事件
  • @KrisErickson 感谢您的提琴,我已经更新了代码以便它可以明确地检测到更改,请按照更新后的提琴jsfiddle.net/7CM6k/3
  • @TarunGupta 是的,它正在处理触发器,但没有更改值。当 hidden 的值发生变化时,浏览器不会触发 change 事件,您必须手动进行。
  • 这个答案的第一部分关于绑定到所有隐藏字段非常有帮助。谢谢!
【解决方案4】:
$('#userid').change(function(){
  //fire your ajax call  
});

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

【讨论】:

    【解决方案5】:

    可以使用Object.defineProperty() 来重新定义输入元素的“值”属性并在其更改期间执行任何操作。

    Object.defineProperty() 允许我们为属性定义 getter 和 setter,从而控制它。

    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/

    【讨论】:

    • 我喜欢这种方法,尤其是因为其他人的回答是“自己触发改变”......这并不总是可行的。
    • 这几乎对我有用,除了隐藏字段中的最终值之外的所有内容实际上都没有改变,如果你检查 jsfiddle 隐藏字段值不会从 '123' 改变(使用铬)
    • 非常接近,但正如其他人所提到的,它不维护对该字段的原始 mutator/setter 的引用,因此更新无法影响隐藏输入本身。我正在发布一个新的解决方案,它结合了这种方法的各个部分和来自stackoverflow.com/a/38802602/4342230 的解决方案
    【解决方案6】:

    在Viktar's answer 的基础上,您可以在给定的隐藏输入元素上调用一次,以确保在输入元素的值发生更改时触发后续更改事件:

    /**
     * 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]);
    });
    

    【讨论】:

    • 2020年,我以前的方法已经不行了。这种方法最适合我
    • 你让不可能成为可能。希望我能给你一百万次投票
    • 谢谢你,@ahmednawazbutt!
    【解决方案7】:

    此示例在每次隐藏草稿字段更改其值时返回草稿字段值(chrome 浏览器):

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

    【讨论】:

      【解决方案8】:

      虽然这个帖子有 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");
          });
      }
      

      【讨论】:

      • 模糊事件仅在输入失去焦点时触发。不是对隐藏输入的有效响应
      猜你喜欢
      • 1970-01-01
      • 2012-09-29
      • 1970-01-01
      • 1970-01-01
      • 2011-10-21
      • 2013-07-23
      • 1970-01-01
      • 2012-12-21
      • 1970-01-01
      相关资源
      最近更新 更多