Using javascript MutationObserver to detect a value change in an input tag

I want to determine when the text / value in the input field changes. So I read a lot of examples and try to execute the following code. But it doesn’t work .here script viewing . Even if I change the value to js code, I want to find that change.

HTML

<input type="text" id="exNumber"/> 

Javascript

 var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { // console.log('Mutation type: ' + mutation.type); if ( mutation.type == 'childList' ) { if (mutation.addedNodes.length >= 1) { if (mutation.addedNodes[0].nodeName != '#text') { // console.log('Added ' + mutation.addedNodes[0].tagName + ' tag.'); } } else if (mutation.removedNodes.length >= 1) { // console.log('Removed ' + mutation.removedNodes[0].tagName + ' tag.') } } if (mutation.type == 'attributes') { console.log('Modified ' + mutation.attributeName + ' attribute.') } }); }); var observerConfig = { attributes: true, childList: false, characterData: false }; // Listen to all changes to body and child nodes var targetNode = document.getElementById("exNumber"); observer.observe(targetNode, observerConfig); 
+10
javascript html
source share
3 answers

To understand what is going on, it is necessary to clarify the difference between an attribute (content attribute) and a property (IDL attribute). I will not expand on this since there are already great answers in SO covering the topic:

  • Properties and Attributes in HTML
  • .prop () vs. attr ()
  • What happens for .setAttribute vs.attribute =?

When you change the contents of an input element by typing or using JS:

 targetNode.value="foo"; 

the browser updates the value property but not the value attribute (which instead reflects the defaultValue property).

Then, if we look at the MutationObserver specification , we will see that attributes are one of the members of the object that can be used. Therefore, if you explicitly value attribute:

 targetNode.setAttribute("value", "foo"); 

MutationObserver will notify you of an attribute change. But there is nothing like properties in the specification list: the value property cannot be detected .

If you want to determine when the user changes the contents of your input element, the input event is the easiest way. If you need to catch JS modifications go to setInterval and compare the new value with the old one.

Check this question to learn about the various alternatives and its limitations.

+16
source share

The value of the property can be observed , do not waste your time.

 function changeValue (event, target) { document.querySelector("#" + target).value = new Date().getTime(); } function changeContentValue () { document.querySelector("#content").value = new Date().getTime(); } Object.defineProperty(document.querySelector("#content"), "value", { set: function (t) { alert('#changed content value'); var caller = arguments.callee ? (arguments.callee.caller ? arguments.callee.caller : arguments.callee) : '' console.log('this =>', this); console.log('event => ', event || window.event); console.log('caller => ', caller); return this.textContent = t; } }); 
 <form id="form" name="form" action="test.php" method="post"> <input id="writer" type="text" name="writer" value="" placeholder="writer" /> <br /> <textarea id="content" name="content" placeholder="content" ></textarea> <br /> <button type="button" >Submit (no action)</button> </form> <button type="button" onClick="changeValue(this, 'content')">Change Content</button> 
+4
source share

This works, saves, and combines the original installer and the receiver, so everything else in your area still works.

 var registered = []; var setDetectChangeHandler = function(field) { if (!registered.includes(field)) { var superProps = Object.getPrototypeOf(field); var superSet = Object.getOwnPropertyDescriptor(superProps, "value").set; var superGet = Object.getOwnPropertyDescriptor(superProps, "value").get; var newProps = { get: function() { return superGet.apply(this, arguments); }, set: function (t) { var _this = this; setTimeout( function() { _this.dispatchEvent(new Event("change")); }, 50); return superSet.apply(this, arguments); } }; Object.defineProperty(field, "value", newProps); registered.push(field); } } 
0
source share

All Articles