Could someone please explain me why when trying to validate a radio button without using NgFor for the options works:
@Component({
selector: 'rio-app',
template: `
<form #myForm="ngForm">
<label>
Male:
<input type="radio" name="gender" value="Male"
ngModel required #gender="ngModel"
/>
</label>
<label>
Female:
<input type="radio" name="gender" value="Female"
ngModel required #gender="ngModel"
/>
</label>
<div [hidden]="!gender.hasError('required')">
The gender is required
</div>
</form>
`
})
export class AppComponent {}
Plunker
But if I try to do the same thing using NgFor
it fails:
@Component({
selector: 'rio-app',
template: `
<form #myForm="ngForm">
<label *ngFor="let gender of genders">
{{ gender }}:
<input type="radio" name="gender" [value]="gender"
ngModel required #myGender="ngModel"
/>
</label>
<div [hidden]="!myGender.hasError('required')">
The gender is required
</div>
</form>
`
})
export class AppComponent {
genders = ['Male', 'Female']
}
Plunker
I'm getting an error message in the browser's console that says:
Cannot read property 'hasError' of undefined
Any ideas?
So I ended up opening an issue in the Angular repo and one person (@alexzuza) gave me a good answer that I want to share with you for future references:
import { Component } from '@angular/core';
@Component({
selector: 'rio-app',
template: `
<form #myForm="ngForm">
<input type="text" />
<ng-container *ngFor="let gender of genders; let isLast = last">
<label>
{{ gender }}:
<input type="radio" name="gender" [value]="gender"
ngModel required #myGender="ngModel"
/>
</label>
<div *ngIf="isLast" [hidden]="!myGender.hasError('required')">
The gender is required
</div>
</ng-container>
</form>
`
})
export class AppComponent {
genders = ['Male', 'Female']
}
To my understanding, the trick is to do everything inside of the NgFor
using the <ng-container>
because every variable created inside the loop will have block scope.
Here's a working plunker
Looking at that second plunker it seems that the template reference variable #myGender
defined within the *ngFor
isn't visible outside i.e. in that error message div
.
But you do have access at that level to #myForm
though, so you can use that to check for errors on the gender FormControl.
<div [hidden]="!myForm.controls.gender?.hasError('required')">
The gender is required
</div>
From the Angular doco I knew that the gender variable defined in the *ngFor
definition wouldn't be visible but I wasn't sure about template variables within that block. Someone else might provide us with a better explanation of that.
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