Detect programmatic changes on input type text

If you're dealing with a modern browser, you can try with something like this:

var input = document.getElementById('test');
input._value = input.value;
Object.defineProperty(input, "value", {
    get: function() {return this._value;},
    set: function(v) {
        // Do your stuff
        this._value = v;
    }
});

This solution is good if you actually don't expect any user input (i.e., hidden type input fields), because it's extremely destructive of the DOM basic functionality. Keep that in mind.


I find the simplest way is to actually trigger the event manually:

document.getElementById('test').value = 'bbb';
var evt = new CustomEvent('change');
document.getElementById('test').dispatchEvent(evt);

Just listening to the change event is error-prone when the value is changed programmatically. But since you are changing the value, add two lines and fire the change event, with a CustomEvent.

then you'll be able to catch this change event, either inline:

<input id="test" onchange="console.log(this)">

or with a listener:

document.getElementById('test').addEventListener('change',function(event) {
    console.log(event.target);
});

this have the advantage that if you have an input which can be changed by the user, you can catch both those events (from the user or the script)

this however depends on the fact that you are yourself programmatically changing the value of the input. If you are using libraries (such as datepickr) that change the values of your inputs you may have to get in the code and add those two lines at the right place.

Live Demo:

// input node reference
const inputElem = document.querySelector('input')

// bind "change" event listener
inputElem.addEventListener('change', e => console.log(e.target.value))

// programatically change the input's value every 1 second
setInterval(() => { 
  // generate random value
  inputElem.value = Math.random() * 100 | 0; 
  
  // simulate the "change" event
  var evt = new CustomEvent('change')
  inputElem.dispatchEvent(evt)
}, 1000);
<input>