My objective is to observe an input value and trigger a handler when its value gets changed programmatically. I only need it for modern browsers.
I have tried many combinations using defineProperty
and this is my latest iteration:
var myInput=document.getElementById("myInput");
Object.defineProperty(myInput,"value",{
get:function(){
return this.getAttribute("value");
},
set:function(val){
console.log("set");
// handle value change here
this.setAttribute("value",val);
}
});
myInput.value="new value"; // should trigger console.log and handler
This seems to do what I expect, but it feels like a hack as I am overriding the existing value property and playing with the dual status of value
(attribute and property). It also breaks the change
event that doesn't seem to like the modified property.
My other attempts:
- a setTimeout/setInterval loop, but this is not clean either
- various
watch
andobserve
polyfills, but they break for an input value property
What would be a proper way to achieve the same result?
Live demo: http://jsfiddle.net/L7Emx/4/
[Edit] To clarify: My code is watching an input element where other applications can push updates (as a result of ajax calls for example, or as a result of changes in other fields). I have no control on how the other applications push updates, I am just an observer.
[Edit 2] To clarify what I mean by "modern browser", I'd be very happy with a solution that works on IE 11 and Chrome 30.
[Update] Updated demo based on the accepted answer: http://jsfiddle.net/L7Emx/10/
The trick suggested by @mohit-jain is to add a second input for user interaction.
Since you are already using polyfills for watch/observe, etc, let me take the opportunity to suggest to you Angularjs.
It offers exactly this functionality in the form of it's ng-models. You can put watchers on the model's value, and when it changes, you can then call other functions.
Here is a very simple, but working solution to what you want:
http://jsfiddle.net/RedDevil/jv8pK/
Basically, make a text input and bind it to a model:
then put a watcher on the angularjs model on this input in the controller.