186

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?

Alexander Abakumov
  • 13,617
  • 16
  • 88
  • 129
Gabriel Petrovay
  • 20,476
  • 22
  • 97
  • 168
  • http://rakshasingh.weebly.com/1/post/2012/12/what-is-the-difference-between-oninput-and-onchange-events-in-javascript.html Note that oninput is not supported in older browser. You could use then: onchange, onpaste and onkeyup as a workaround. PS: oninput event is also buggy in IE9 and it is not fired on deletion. – A. Wolff Jun 11 '13 at 15:09
  • 2
    input fires more often, like after a keypress, whereas change basically fires when the input is blurred and the value is not what it was when the input was focused. – dandavis Jun 11 '13 at 15:10
  • 1
    The `input` event also captures pasting. See http://stackoverflow.com/questions/15727324/for-a-javascript-autocomplete-search-box-must-we-use-the-input-event-handler – Antony Jun 11 '13 at 15:51
  • 2
    TLDR: input fires as you type, change fire when you click outside – Muhammad Umer Mar 05 '18 at 17:09

5 Answers5

179

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 content
  • onchange:
    • If it is an <input />: change + lose focus
    • If it is a <select>: change option

$("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>
Kick Buttowski
  • 6,709
  • 13
  • 37
  • 58
Ionică Bizău
  • 109,027
  • 88
  • 289
  • 474
  • 11
    I'm still unclear on the difference between the two. They sound very similar from your descriptions. – Justin Morgan - On strike Jun 11 '13 at 15:35
  • 15
    @JustinMorgan Like in the JSFiddle example, the `onchange` occurs "when the element loses the focus" while the `oninput` occurs on every text change. – Ionică Bizău Jun 11 '13 at 15:46
  • 6
    The difference is that the oninput event occurs immediately after the value of an element has changed, while onchange occurs when the element loses focus, after the content has been changed. – NinoLopezWeb Jul 06 '17 at 14:52
  • 1
    In other words "input" is triggered immediately when any character is changed, deleted or added while "change" is evaluated after the control loses focus and happens only when the value has changed – Adam Moszczyński Oct 10 '17 at 07:26
  • I just tried with Chrome. `onchange` also gets triggered when you hit enter while still focusing. – Rick Mar 24 '20 at 00:32
  • 1
    This explanation is very poor, and verges on being *outright wrong*. [`change`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) events fire specifically when the input value is changed *by the user*. [`input`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event) fires on *all* value changes, regardless of where they come from. – zcoop98 Aug 25 '20 at 17:31
  • @IonicăBizău Select element doesn't lose the focus when its value changes but this answer put ` – user3290525 Sep 26 '21 at 22:42
  • @user3290525 Well, of course you can use the ` – Ionică Bizău Sep 27 '21 at 12:36
35
  • The change event fires in most browsers when content is changed and the element loses focus. It's basically an aggregate of changes. It will not fire for every single change as in the case input 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

Joel H
  • 920
  • 12
  • 12
Gabe
  • 49,577
  • 28
  • 142
  • 181
16

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.

screenshot of the demo

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>
akinuri
  • 10,690
  • 10
  • 65
  • 102
  • 1
    This is awesome. TL;DR: `input` works for all if them if you care about immediate notification. `change` works for all of them if you care about notification on defocus (blur). – Timmmm Mar 10 '23 at 11:11
  • Excellent demo/answer. It shows the 5 most recent events on the right of each input field, with the most recent being on the far right. – Chrisuu Jun 28 '23 at 00:37
8

TL;DR: The biggest difference is what causes the value change:

  • input events fire on any value changes
  • change events fire on direct user-initiated value changes
    • (The exact details of this vary between input types)

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.

In other words, 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. In addition, change only generally fires when the ending value is different than the starting one (as its name suggests).

For <input> specifically, the exact timing of the change event depends on the input's type attribute. In general:

  • For text-based input types (e.g: search, text, email, password, etc.):
    • When the element loses focus (on blur).
  • For inputs that open some sort of interactive menu (e.g. file, date, color, etc.):
    • When the UI element is closed.
    • If the type has a direct text input mechanism (like date), then it also fires on each input of text (e.g. on each typed digit).
  • For non-textual inputs that are interactive (e.g. checkbox, radio, & range):
    • When the element is left in a new state after interacting with it (e.g. click, drag, keyboard shortcut trigger).

There are a few elements with their own nuances, but these are true in the general case.


Interactive Demo

new Vue({
  el: '#app',
  data: {
    inputs: [],
    changes: [],
    types: ['text', 'email', 'color', 'file', 'date', 'range'],
  },
  methods: {
    logEvent(e, index) {
      this.$set(this[e.type + 's'], index, e.target.value);
    },
  },
});
<link href="https://unpkg.com/bootstrap@4/dist/css/bootstrap.min.css" rel="stylesheet"><script src="https://unpkg.com/vue@2/dist/vue.min.js"></script>

<div id="app">
  <div class="container mw-100 py-3">
    <div v-for="(type, i) in types" class="row mb-2">
      <div class="col-2">
        <span>{{ type.charAt(0).toUpperCase() + type.slice(1) }}:</span>
      </div>
      <div class="col-5">
        <input :type="type" @input="logEvent($event, i)" @change="logEvent($event, i)" />
      </div>
      <div class="col-5">
        <div class="row">
          <div class="col-6 text-break">
            <span>Input: <span style="color: red">{{ inputs[i] }}</span></span>
          </div>
          <div class="col-6 text-break">
            <span>Change: <span style="color: blue">{{ changes[i] }}</span></span>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
zcoop98
  • 2,590
  • 1
  • 18
  • 31
3

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

Joel H
  • 920
  • 12
  • 12