Click handler does not start when target element is moved

Consider the following demo https://stackblitz.com/edit/angular-pur1dt

I have reactive form control with a synchronization validator and an error message displayed below the field when it is invalid.

The check is triggered when the control loses focus. Below the control is a button with a click handler. The problem is that when I press the button, the control loses focus, validation occurs, an error message is displayed and the button moves down. And presumably this prevents the click handler from executing. Any suggestions why this is happening and how to solve the problem?

I updated the demo with comments. Note: only the button under the input will reproduce the problem. The title will not be updated after the first click.

+4
source share
3 answers

The problem seems to be related to the order in which DOM events are triggered

According to MDN:

A click event is fired when a pointing device button (usually the main mouse button) is pressed and released on a single item.

https://developer.mozilla.org/en-US/docs/Web/Events/click

In this example, the element moves the moment you blurenter - because the verification takes place instantly, shows an error and resets the button.

, , , - . click

:

  • on mousedown
  • , mousedown mouseup, mousedown
  • ..

mousedown https://jsfiddle.net/gjbgqqpo/

, :)

+1

№ 7113 GitHub. , , , click.

, this stackblitz. isClicking , mousedown, reset, click.

<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;
  }
}

, setTimeout mousedown isClicking . , .

+4

, , . , .

- autofocus . Angular " , ." . FormControl. name.untouched false true.

you can observe this if you add extra debugging bindings to your template. eg.

<hello name="{{ name }}"></hello>
<form [formGroup]="form">
    <input formControlName="name" autofocus>
    <button (click)="onClick($event)">click OK</button>
</form>
<pre>{{form.controls.name.valid}}</pre>
<pre>{{form.controls.name.untouched}}</pre>
<p [hidden]="form.controls.name.valid || form.controls.name.untouched ">
    Invalid :)
</p>
<button (click)="onClick2($event)">click NOT ok</button>

If you want to hide the error message when the user presses the bottom button, you must remove autofocusor reset the form check when called onClick2(). Alternatively, you can simply display an error message when the form has an error. Angular says A control is untouched if the user has not yet triggered a blur event on it.When the bottom button is pressed, a blur event occurs.

Why not just change the template binding to the error message

<p [hidden]="!form.controls.name.valid || form.controls.name.untouched">
    Invalid :)
</p>
0
source

Source: https://habr.com/ru/post/1691471/


All Articles