Consider the following demo https://stackblitz.com/edit/angular-pur1dt
I have reactive form control with sync validator and error message shown below the field when it is invalidated.
Validation is triggered when control loses focus. Below the control there is a button that has a click handler. The problem is that when I click the button, control loses focus, validation happens, error message shown and moves the button down. And supposedly this prevents click handler from executing. Any suggestions why this happens and how to fix the issue?
I've updated the demo with comments. Note: only button below the input will reproduce the issue. The title wont be updated after you click it for the first time.
The problem was discussed in issue #7113 on GitHub. It is caused by the fact that validation is performed when the input field loses focus, before the click on the button has a chance to complete and trigger the click
event.
A possible workaround is to use a flag to keep the message hidden while clicking the button is under way, as shown in this stackblitz. In the code below, the isClicking
flag is set when clicking starts on the mousedown
event, and it is reset when the click
event completes.
<p #errorMsg [hidden]="(errorMsg.hidden && isClicking) || form.controls.name.valid || form.controls.name.untouched ">
Invalid :)
</p>
<button (mousedown)="onMouseDown($event)" (click)="onClick2($event)">click NOT ok</button>
export class AppComponent {
isClicking = false;
...
onMouseDown(event) {
this.isClicking = true;
setTimeout(() => {
// The click action began but was not completed after two seconds
this.isClicking = false;
}, 2000);
}
onClick2(event) {
console.log(event);
this.name = "NOT";
this.isClicking = false;
}
}
You can improve that solution by replacing the setTimeout
with a procedure to capture the mouse in the mousedown
event handler, and resetting isClicking
when the capture is lost. It would account for the cases where the user leaves the button without completing the click.
The issue seem to relate to DOM events triggering order
According to MDN:
The click event is fired when a pointing device button (usually a mouse's primary button) is pressed and released on a single element.
https://developer.mozilla.org/en-US/docs/Web/Events/click
In the given example the element moves the moment you blur
the input -- because the validation happens instantly, reveals the error and repositions the button.
Therefore mouse is down when while over the button, but when its up -- the button is repositioned. So click
wont be triggered on the button
There are several options to workaround that:
mousedown
delay the error revealmousedown
and mouseup
happened, if mousedown
happened on the buttonHere's an example with mousedown
event handling
https://jsfiddle.net/gjbgqqpo/
Hope this helps :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With