问题
I have a data gathering component which includes 'cancel' button to cancel the whole process. The problem is, if some of the HTML input fields which are validated by Angular 2 validators have focus, and are not valid, and I press the cancel button, the component is not removed. Instead, validators will fire and the cancel button press will be ignored. I have to press it for the second time, after the validators complain, to make the component disappear.Cancel button itself simply triggers routing away from the component. Relevant code:
component.html
<form [formGroup]="addReminderForm" (ngSubmit)="onSubmit(addReminderForm.value)">
<input type="text" [formControl]="addReminderForm.controls['text']" />
<div class="error" *ngIf="addReminderForm.controls['text'].hasError('required') &&
addReminderForm.controls['text'].touched">You must enter reminder text</div>
<button type="submit" [disabled]="!addReminderForm.valid" >Add Reminder</button>
</form>
<button (click)="cancel()">Cancel</button>
component.ts:
ngOnInit() {
this.addReminderForm = this.fb.group({
'text': ['', Validators.compose([Validators.required, Validators.maxLength(20)])]
});
}
cancel() {
// Simply navigate back to reminders view
this.router.navigate(['../'], { relativeTo: this.route }); // Go up to parent route
}
I have no idea why this happens. Any ideas?
回答1:
Change the event from (click) to (mousedown). Mousedown is invoked before blur event.
So instead of this <button (click)="cancel()">Cancel</button>
try this: <button (mousedown)="cancel()">Cancel</button>
回答2:
Try using button type="reset" like:
<form [formGroup]="heroForm" (ngSubmit)="onSubmit()" novalidate>
...
<div>
<button type="submit" [disabled]="heroForm.pristine">Save</button>
<button type="reset" (click)="revert()"[disabled]="heroForm.pristine">Revert o Cancel</button>
</div>
</form>
In your component class:
revert() { this.ngOnChanges(); }
For more information in https://angular.io/guide/reactive-forms
I hope to help you.
回答3:
The cause is that form validation fires as soon as the blur event fires. So it happens before the cancel click is registered.
I can only figure out one workaround - have a flag in your component that is initially set to false to know when to show the errors.
Only set it to true when you want validations to 'fire'.
So if the form loads and the user clicks in a field and then clicks cancel, the flag is still false and so no validations show. If the user clicks submit you turn the flag on, causing validations to be shown.
For example, this form has a span block that is used to show validation errors and it is protected by and *ngIf
for the flag. Also protected is the 'checking-field' class for the input itself - this just adds a red border around the input if there is an error. So the flag must be true for the red border and the validation errors to show up.
<form [formGroup]="form" (ngSubmit)="onSubmit(form.value)">
<div class="modal-body">
<input #nameElement id="template-name" (blur)="onBlur($event.target)"
[formControl]="name" (keyup)="keyUp($event)" class="form-control"
[ngClass]="{'checking-field': isShowError}"
placeholder="Name this template">
<span class="help-block" *ngIf="isShowError">
<span class="text-danger" *ngIf="form.get('name').hasError('minlength')">Name is required</span>
<span class="text-danger" *ngIf="form.get('name').hasError('noDifference')">Name must be different</span>
</span>
</div>
</form>
OnSubmit starts like this:
onSubmit(data: any):void {
this.isShowError = true;
if (this.form.valid) ...
which ensure validation errors will show when user clicks submit. They WON'T show up when a field loses focus, because the flag will be false.
However, you MAY be able to get round that by an ugly hack, as follows (cumbersome also since you then need a blur handler for all fields on the form!).
Add another flag to track when the user clicks the cancel button, and for each field on the form, in the (blur) handler, check it within a timeout, like this:
setTimeout(() => {if (!userClickedCancel) this.isShowError = true}, 500);
Then in the cancel click handler:
this.userClickedCancel = true;
This means the cancel code should change the flag before the timeout expires in the handlers to check it's value.
** NOTE: If you are 'dismissing' the form and not navigating away **
Also, if you are not navigating away but maybe 'hiding' the form (or closing a modal), you should also set the isShowError
flag to false in the cancel handler (for cases where user hits submit, form is invalid, then they click cancel, and then you reload the form again).
来源:https://stackoverflow.com/questions/45015403/angular-2-form-validators-messing-with-the-cancel-button