33

I have a hidden field called #myHiddenField say.

The content of this field is programatically changed at various places.

I'd like a method that detects that change. The change event won't fire unless I type into the field but this is impossible.

Is there a jQuery way to detect programatic content change in a field?

griegs
  • 22,624
  • 33
  • 128
  • 205

5 Answers5

34

You should be able to trigger the change event with:

$('#myHiddenField').change();

OR

$('#myHiddenField').trigger('change');

Of course this will require the block of code responsible for updating the filed to make one of those calls after it has done its work.

prodigitalson
  • 60,050
  • 10
  • 100
  • 114
  • Have moved the place where the field is being set into its own function and used the trigger command. Works like a treat thank you – griegs Nov 17 '10 at 00:21
  • @griegs Hey, that kind of sounds like... my first suggestion :P – alex Nov 17 '10 at 00:26
  • @alex, yeah ok +1 but i think this one shows it better for future users. :) – griegs Nov 17 '10 at 00:27
7

The DOM cannot detect the programmatic raising of events. I actually ran into this yesterday. I don't remember where I read it, but the solution was to actually call .trigger() on the jQuery element. jQuery Doc

pinkfloydx33
  • 11,863
  • 3
  • 46
  • 63
6

Case 1: You want to change the value programmatically yourself and just want to dispatch an event when the value is changed.

$('#myfield').text('New value');
//$('#myfield').val('New value');
$('#myfield').trigger('change');

Case 2:

Suppose, you want to detect the programmatic change to a field which is not written by you. So, there is no way you can trigger 'change' event.

In this case, Use 'DOMSubtreeModified' to detect programmatic changes to descendant elements of a parent element.

Example:

<div id="product-addons-total">
    <div id="total_price">200</div>
</div>

$(document).ready(function() {

    jQuery('#product-addons-total').on("DOMSubtreeModified",function(){
        console.log('content changed');
        //tamp_price_change_handler();
    });
});

Now, if the value of the "total_price" changes somehow programmatically, it will fire "DOMSubtreeModified" event. Example:

jQuery('#total_price').text('300');

Caution for Case 2: DOMSubtreeModified can create an infinite loop and greatly degrade performance. Instead, it is encouraged to use MutationObserver.

Example with MutationObserver:

// create an observer instance
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.type);        
  });    
});

// Let's configure the observer
var config = { childList: true, subtree:true, attributes: true, characterData: true,
    characterDataOldValue: true, attributeOldValue: true };
//Let's get a node.
var target = jQuery('#product-addons-total').get(0); 
// Let's pass the target and configuration to the observe function.
observer.observe(target, config); 

Case 3:

The above ways can detect a change in the DOM. But if you want to change the value of an input field programmatically, then these events won't fire. In that case, the only way is to trigger an event manually. So, first change the value of an input field and then trigger an event manually.

$('#inputfield').val(456465).trigger('change');

//Now the change event will fire.
$('#inputfield').on('change', function() {  
    console.log('input filed has been changed');
});
Md. Zubaer Ahammed
  • 931
  • 11
  • 13
  • 1
    It appears this doesn't work for changing value of inputs. – dlsso Apr 13 '17 at 17:03
  • 1
    @dlsso Yes, these events (both DOMSubtreeModified and MutationObserver) can only detect changes in the DOM. Such as when a node is modified, a node is added or deleted, an attribute is changed, etc. But when you programmatically change the value of an input field these events will not notice a change in the DOM. In this case, you will need to manually fire an event after changing the value of an input field programmatically. Such as ```$('#inputfield').val(456465).trigger('change'); ```Then handle event with ```$('#inputfield').on('change', function(){ console.log('changed'); });``` – Md. Zubaer Ahammed May 14 '17 at 12:01
0

Setting the value using .val() in jQuery doesn't trigger a change event so you'll have to use .change() or .trigger('change') to trigger an change event. You can choose to use either .change(function() { ... }) or .on('change', function() { ... } to detect the change event to the field.

$('#myHiddenField').change(function() {
    alert('content changed to: ' + $('#myHiddenField').val());
});

$('#btnChange').click(function() {
    $('#myHiddenField').val("new content");
    $('#myHiddenField').change();
});

https://jsfiddle.net/qeg5of2a/1/

or

$('#myHiddenField').on('change', function() {
    alert('content changed to: ' + $('#myHiddenField').val());
});

$('#btnChange').click(function() {
    $('#myHiddenField').val("new content");
    $('#myHiddenField').trigger('change');
});

https://jsfiddle.net/qeg5of2a/2/

.change is just shortcut for .on('change', handler) and .trigger('change') so either is fine

Arne H. Bitubekk
  • 2,963
  • 1
  • 27
  • 34
0

I couldn't get the change event to fire when the field changed by Blazor of the .NET framework, but alternatively you could redefine the value property of the input field:

Object.defineProperty($('#myHiddenField')[0], 'value', {
    get() { debugger; return "1"; },
    set(value) { debugger; }
})
Protector one
  • 6,926
  • 5
  • 62
  • 86