Reputation: 1035
I have been using reactive form in my Angular project in many places and last week we decided to optimize our code a bit. During code review I have found an issue regarding showing form validation messages in HTML.
So I have used below code to show validation error messages:
<form [formGroup]="form">
<div>
<input formControlName="firstName">
<div *ngIf="form.controls.firstName.errors && (form.controls.firstName.touched || form.controls.firstName.dirty)">
This field is required
</div>
</div>
</form>
It seems fine, but what if I replace form.controls.firstName.errors
with !form.controls.firstName.valid
See below:
<form [formGroup]="form">
<div>
<input formControlName="firstName">
<div *ngIf="!form.controls.firstName.valid && (form.controls.firstName.touched || form.controls.firstName.dirty)">
This field is required
</div>
</div>
</form>
I couldn't see any difference at all but in my team some of team mates has opinion that we should use !form.controls.firstName.valid
and we had long discussion on this small issue. I still didn't convince with my team mates. For me if form
has an error
then it's status will be invalid
or form
is invalid
because it has an error
.
Could anyone suggest me which option we should follow and is correct fundamentally.
Many thanks in advance.
Upvotes: 1
Views: 143
Reputation: 20599
A validator function is going to return an object literal of errors if there is an error or null otherwise. The falsiness of the result is how angular know determines if a control is valid. So you can presume that the result will be functionally equivalent if you use .error
or !...valid
.
The being said using !...valid
(or more appropriately .invalid
) is the more definitive approach and if you look at Angular's examples that is how they do it.
I look at this way: Who knows in the future of if the behavior you're depending on is always going to be the same? There might be a legitimate case in the future where errors is null but the control is still invalid. Best to take the most explicit approach when there is no additional cost in doing so.
EDIT
Actually look at the source for AbstractControl
potentially errors can be empty but the control can still be invalid depending on the implementation of the _anyControls()
function:
get invalid(): boolean { return this.status === INVALID; }
/*...*/
private _calculateStatus(): string {
if (this._allControlsDisabled()) return DISABLED;
if (this.errors) return INVALID;
if (this._anyControlsHaveStatus(PENDING)) return PENDING;
/* if the condition below is true that means the control will be invalid
* but errors will be null. */
if (this._anyControlsHaveStatus(INVALID)) return INVALID;
return VALID;
}
Given that conditions are possible that errors
can be null but the control status still be invalid
, then you should definitely be checking invalid
and not errors
.
Upvotes: 2