Reputation: 11000
Can not acces it in the same way as in Angular docs, so must grab the FormGroup instance first and find FormControl instance in there.. I wonder why? This example works:
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="username">Username</label>
<input
type="text"
name="username"
class="form-control"
formControlName="username"
>
<div *ngIf="myForm.controls.username.invalid" class="alert alert-danger">
username is required
</div>
</div>
While this throws error (difference between these only in *ngIf statement):
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="username">Username</label>
<input
type="text"
name="username"
class="form-control"
formControlName="username"
>
<div *ngIf="username.invalid" class="alert alert-danger">
username is required
</div>
</div>
Cannot read property 'invalid' of undefined
form.component:
import {Component} from '@angular/core';
import {FormGroup, FormControl, Validators} from '@angular/forms';
@Component({
selector: 'sign-up',
templateUrl: 'app/sign-up.component.html'
})
export class SignUpComponent {
myForm = new FormGroup({
username: new FormControl('username', Validators.required),
password: new FormControl('', Validators.required),
});
}
Upvotes: 17
Views: 32761
Reputation: 11
Another option is to check if username is defined, replacing the following
<div *ngIf="username.invalid" class="alert alert-danger">
with the following, should also work
<div *ngIf="username !== undefined && username.invalid" class="alert alert-danger">
Upvotes: 0
Reputation: 24874
It throws error because you don't have a variable called username
or password
.
In order to solve this, you could either:
TS:
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
readonly usernameCtrl = this.formBuilder.control('username', Validators.required);
readonly passwordCtrl = this.formBuilder.control('', Validators.required);
readonly formGroup = this.formBuilder.group({
username: this.usernameCtrl,
password: this.passwordCtrl
});
HTML:
<div
*ngIf="userNameCtrl.invalid" class="alert alert-danger"
>
username is required
</div>
AbstractControl#get
to grab the control:HTML:
<div
*ngIf="formGroup.get('username').invalid" class="alert alert-danger"
>
username is required
</div>
AbstractControl#hasError
so you'll be able to specify different messages for each existent validation:HTML:
<div
*ngIf="formGroup.hasError('required', 'username')" class="alert alert-danger"
>
username is required
</div>
Upvotes: 26
Reputation: 11
actually I'm just new in Angular, I'm just using it for a month and also searching for some answers hehe but in your Component add a getter like this:
export class SignUpComponent {
myForm = new FormGroup({
username: new FormControl('', Validators.required),
password: new FormControl('', Validators.required),
});
get username(){
return this.myForm.controls['username'];
}
}
Upvotes: 1
Reputation: 116
In the ts file add:
get username() { return this.myForm.get('username'); }
get password() { return this.myForm.get('password'); } }
Upvotes: 1
Reputation: 21
I had the same problem, I add 'this' to "myForm.controls....".It helped me.
Instead of:
<div *ngIf="myForm.controls.username.invalid" class="alert alert-danger">
username is required
</div>
Do:
<div *ngIf="this.myForm.controls.username.invalid" class="alert alert-danger">
username is required
</div>
Hope this helped you.
Upvotes: 1
Reputation: 157
For me works:
form.component:
getFormControl(name) {
return this.Form.get(name);
}
template:
<input
type="text"
name="username"
class="form-control"
formControlName="username"
>
<div *ngIf="getFormControl('username').invalid" class="alert alert-danger">
username is required
</div>
Upvotes: 6
Reputation: 982
You can solve this issue using a Form Group and defining the corresponding getters in your controller. In order to achieve this goal:
In the controller:
1) Remove the form control variables definition and initialization
usernameCtrl: FormControl;
passwordCtrl: FormControl;
...
this.usernameCtrl = this.formBuilder.control('username',Validators.required);
this.passwordCtrl = this.formBuilder.control('', Validators.required);
2)Change the form group initialization to this
ngOnInit() {
this.myForm = this.formBuilder.group({
username: ['usename', Validators.required]
password: ['', Validators.required]
});
}
3) Add the getters
get username() { return this.myForm.get('username'); }
get password() { return this.myForm.get('password'); }
In the template:
1) add a parent div with [formGroup]="MyForm"
<div [formGroup]="myForm">
...
</div>
2) change [formControl]="usernameCtrl" for forcontrolName=username and *ngIf="usernameCtrl.invalid" for *ngIf="username.invalid"
<input type="text"
name="username"
class="form-control"
formControlName="username">
<div *ngIf="username.invalid" class="alert alert-danger">
username is required
</div>
3) change [formControl]="passwordCtrl" for forcontrolName=password and *ngIf="passwordCtrl.invalid" for *ngIf="password.invalid" te.
<input type="text"
name="password"
class="form-control"
formControlName="password">
<div *ngIf="password.invalid" class="alert alert-danger">
password is required
</div>
Upvotes: 11