jQuery-检测隐藏输入字段上的值更改


270

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

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

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

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

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

2
如果通过ajax响应进行更新,为什么不在响应的成功函数中触发新的ajax请求呢?
BonyT 2011年

2
如果您要的是$('#userid')。val()将为您提供值
BonyT 2011年

更新:现在,当更新隐藏字段的值时,将触发一个更改事件。
史蒂文

Answers:


622

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

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

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

这样的话

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

应该能按预期工作。


5
.trigger()一般最好使用经过短短打电话change()
汉娜(Hanna)2013年

1
它可以工作,但是似乎触发了两次更改事件!。就像我放了这段代码一样,它会触发两次,如果我移除了代码,则没有触发器。
来自委内瑞拉的Janx

1
为了使它的行为与change事件相同,您应该添加代码setUserID()以检查该值是否确实更改。if ($('#userid').val() != myVaule) { // set val() and trigger change }
nnattawat 2015年

1
如果您尝试捕获通过JavaScript进行更改的“更改”事件,则此功能特别有用,否则.change(handler)或.on(“ change”,handler)无法捕获javascript所做的更改
JJK

7
因此,如果我无法控制更改隐藏字段值的功能(即无法触发触发器),那么此解决方案将无法正常工作,对吧?
osama yaccoub

31

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

据信,mutationobserver也不会因为文本字段内的更改而被解雇(无论是否隐藏)
Ole Albers

3
很棒!@OleAlbers - OP询问input[type=hidden]
吉文

1
我将其与使用jquery的map命令来检索隐藏的输入字段值的集合的函数结合使用。非常感谢@lulalala!
亚当·琼斯

2
简单易懂。与“更改值时必须触发事件”解决方案相反,此解决方案不依赖于程序员在更改值时就可以访问代码,因此只要您不这样做,它就更加有用。不必支持早于IE11的版本。对我来说很棒。谢谢
Joe Salazar '18

很好的解决方案!谢谢!由于某种原因,该方法trigger('change')对我不起作用,因此我创建了一个CustomEvent,进行了注册,然后element.dispatchEvent(myCustomEvent)
tbutcaru

8

您可以简单地使用以下功能,也可以更改type元素。

 $("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/


1
不适用于我...无论如何,如何将价值粘贴到“隐藏字段”中?:/
SimonDugré2014年

嘿,谢谢,粘贴不应该在那里,但是更改可以检测到隐藏的字段更改事件
Tarun Gupta 2014年

@KrisErickson感谢小提琴,我已经更新了代码,以便可以明确地检测到更改,请按照更新的小提琴jsfiddle.net/7CM6k/3
Tarun Gupta

1
@TarunGupta是的,它在触发器上起作用,但不更改值。当隐藏值的值发生更改时,浏览器不会触发change事件,您必须手动执行。
克里斯·埃里克森

关于绑定到所有隐藏字段的答案的第一部分非常有帮助。谢谢!
乍得2015年

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

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

4

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

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/


1
我喜欢这种方法,尤其是因为其他所有人的答案都是“自己触发更改”……这并不总是可行的。
sMyles

1
这几乎对我有用,除了隐藏字段中的最终值以外,其他所有内容实际上都没有更改,如果您检查jsfiddle,则隐藏字段值不会从'123'更改(使用Chrome)
MetaGuru

非常接近,但是正如其他人提到的那样,它不维护对该字段的原始更改器/设置器的引用,因此更新无法影响隐藏的输入本身。我发布了一个新的解决方案,其中包含了这种方法的一部分,以及stackoverflow.com/a/38802602/4342230的
GuyPaddock

0

每当隐藏的草稿字段更改其值时,此示例将返回草稿字段值(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  });

       }
  };
})();

0

建立在Viktar的答案的基础上,这是一个实现,您可以在给定的隐藏输入元素上调用一次实现,以确保只要输入元素的值发生更改,就会触发后续的change事件:

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

-4

尽管此线程已有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");
    });
}

3
仅当输入失去焦点时才触发模糊事件。对于隐藏的输入不是有效的响应
manuerumx 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.