Difference between "change" and "input" event for an `input` element
JavascriptJqueryEventsDomJavascript Problem Overview
Can someone tell me what the difference between the change
and input
events is?
I am using jQuery for adding them:
$('input[type="text"]').on('change', function() {
alert($(this).val());
})
It also works with input
instead of change
.
Maybe some difference in the event ordering relative to focus?
Javascript Solutions
Solution 1 - Javascript
According to this post:
-
oninput
event occurs when the text content of an element is changed through the user interface. -
onchange
occurs when the selection, the checked state, or the contents of an element have changed. In some cases, it only occurs when the element loses the focus or when pressing return (Enter) and the value has been changed. The onchange attribute can be used with:<input>
,<select>
, and<textarea>
.
TL;DR:
oninput
: any change made in the text contentonchange
:- If it is an
<input />
: change + lose focus - If it is a
<select>
: change option
- If it is an
$("input, select").on("input", function () {
$("pre").prepend("\nOn input. | " + this.tagName + " | " + this.value);
}).on("change", function () {
$("pre").prepend("\nOn change | " + this.tagName + " | " + this.value);
}).on("focus", function () {
$("pre").prepend("\nOn focus | " + this.tagName + " | " + this.value);
}).on("blur", function () {
$("pre").prepend("\nOn blur | " + this.tagName + " | " + this.value);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" />
<select>
<option>Alice</option>
<option>Bob</option>
<option>Carol</option>
<option>Dave</option>
<option>Emma</option>
</select>
<pre></pre>
Solution 2 - Javascript
-
The
change
event
fires in most browsers when content is changed and the element losesfocus
. It's basically an aggregate of changes. It will not fire for every single change as in the caseinput
event
. -
The
input
event
fires synchronously on change of the content for the element. As such, the event listener tends to fire more frequently. -
Different browsers do not always agree whether a change event should be fired for certain types of interaction
Solution 3 - Javascript
The most significant difference between these two events is what causes the value
change on the <input>
.
According to MDN:
> The input
event fires when the value
of an <input>
, <select>
, or <textarea>
element has been changed.
AKA,
input
fires any time the value
changes.
change
is a little bit more complicated:
> The change
event is fired for <input>
, <select>
, and <textarea>
elements when an alteration to the element's value
is committed by the user. Unlike the input
event, the change
event is not necessarily fired for each alteration to an element's value
.
In other words,
change
fires when the user changes the value
.
When exactly it fires depends on the type
of <input>
:
For...
- "radio" and "checkbox":
- When element is
:checked
, either by keyboard or mouse click
- When element is
- "date" and "file":
- When a change is explicitly committed, ie. selecting a date or file
- "text":
- When the element loses focus after its value has been changed, but not committed
Fair warning that browsers are fickle, and don't always agree on events. This is indeed the spec, however, and you should be able to count on these timings.
Solution 4 - Javascript
It seems that this question has become one of the those questions that I visit from time to time. I'm not a fan of reading walls of text for simple things. So I decided to post a practical answer.
Using the following demo, one can examine which events are fired and in what order.
let eventsToListen = [
"focus",
"blur",
"input",
"change",
];
let inputs = Array.from(
document.querySelectorAll("#inputs :is(input, textarea, select)")
);
inputs.forEach(input => {
input.eventQueue = [];
let queueLimit = eventsToListen.length * 2;
let queueDisplay = input.closest("td").nextElementSibling;
eventsToListen.forEach(event => {
input.addEventListener(event, () => {
input.eventQueue.push(event);
if (input.eventQueue.length > queueLimit) {
Array(input.eventQueue.length - queueLimit).fill(null).forEach(
_ => input.eventQueue.shift()
);
}
queueDisplay.textContent = input.eventQueue.join(", ");
});
});
});
* {
margin: 0;
padding: 0;
box-sizing: inherit;
color: inherit;
font-size: inherit;
font-family: inherit;
line-height: inherit;
}
body {
font-family: sans-serif;
box-sizing: border-box;
background-color: hsl(0, 0%, 90%);
}
#inputs {
margin: 1em;
}
#inputs td {
padding: 0.1em;
}
#inputs td:nth-child(2) :not(input[type=radio]):not(input[type=checkbox]) {
width: 100%;
}
#inputs label {
display: table;
}
#inputs td:last-child {
font-style: italic;
font-size: 0.8em;
opacity: 0.7;
padding-left: 1em;
}
#notices {
margin: 1em;
}
#notices ul {
padding-left: 2em;
line-height: 2;
}
#notices > ul {
margin-top: 0.5em;
}
input[type=radio]:focus,
input[type=checkbox]:focus {
transform: scale(1.5);
}
<table id="inputs">
<tr>
<td>text</td>
<td><input type="text" /></td>
<td></td>
</tr>
<tr>
<td>number</td>
<td><input type="number" /></td>
<td></td>
</tr>
<tr>
<td>textarea</td>
<td><textarea></textarea></td>
<td></td>
</tr>
<tr>
<td>select</td>
<td>
<select>
<option>-</option>
<option>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
</select>
</td>
<td></td>
</tr>
<tr>
<td rowspan="2">radio</td>
<td>
<label><input type="radio" name="something" /> Option 1</label>
</td>
<td></td>
</tr>
<tr>
<td>
<label><input type="radio" name="something" /> Option 2</label>
</td>
<td></td>
</tr>
<tr>
<td style="padding-right: 0.5em">checkbox</td>
<td>
<label><input type="checkbox" name="something2" /> Option 1</label>
</td>
<td></td>
</tr>
</table>
<hr>
<div id="notices">
notice that:
<ul>
<li>"input" event can occur multiple times before a "change" event occurs on text/number/textarea</li>
<li>"input" and "change" event seem to occur together/sequentially on select</li>
<li>"input"/"change" event might occur multiple times before a "blur" event occurs on select
<ul>
<li>when arrow keys are used to select an option</li>
</ul>
</li>
</ul>
</div>
Solution 5 - Javascript
MDN documentation has a clear explanation (not sure when it was added):
> The change event is fired for input
, select
, and textarea
elements when an alteration to the element's value is committed by the user. Unlike the input event, the change event is not necessarily fired for each alteration to an element's value.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event