Reputation: 2193
When a user types something in an <input type="text">
and removes the focus, both blur
and change
are fired.
However, when I do the same thing in JavaScript using the blur()
method, only the blur
event is fired and not the change
event. Is there a reason for this inconsistency?
See this example code (jsfiddle):
<input type="text">
<button>Test</button>
const input = document.querySelector("input")
input.addEventListener("blur", () => console.log("blur"))
input.addEventListener("change", () => console.log("change"))
const button = document.querySelector("button")
button.addEventListener("click", () => {
setTimeout(() => {
input.focus()
input.value = "something"
input.blur()
}, 1000)
})
When clicking the button, after a second, it should focus the input, change the value and blur the input. However, only the blur
event is fired. Doing the same by hand will fire both events.
I like to trigger some validation logic on the change
event and it works perfectly fine in real-live but when I try to recreate the workflow in a unittest it fails and I'm not sure why and how to solve it.
So the alternative question is: How can I trigger the change
event from JavaScript?
Upvotes: 2
Views: 2418
Reputation: 2145
The change
event is specifically emitted when a user interacts with an element. This is built in a was intentional. @see HTMLElement: change event.
Use synthetic events to mimic user interaction in changing the value: input.dispatchEvent(new Event("change"));
Below is a working example with the logic in its own function updateValueWithChangeEvent
.
const input = document.querySelector("input")
input.addEventListener("blur", () => console.log("blur"))
input.addEventListener("change", () => console.log("change"))
// Updates the value of an input and triggers the change Event.
const updateValueWithChangeEvent = (input, value) => {
if (input.value === value) return
input.value = value
input.dispatchEvent(new Event("change"));
}
// Updated example using function above
const button = document.querySelector("button")
button.addEventListener("click", () => {
setTimeout(() => {
// This will update value and trigger change event
updateValueWithChangeEvent(input, "something")
// This will trigger the blur event
input.focus()
input.blur()
}, 1000)
})
<input type="text">
<button>Test</button>
Upvotes: 3
Reputation: 3765
You can trigger an event like this:
const input = document.querySelector("input");
const event = new Event("change");
// blur the input
input.blur();
// dispatch change event manually
input.dispatchEvent(event);
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
Upvotes: 3