Can't acces FormControl instance directly. Cannot read property 'invalid' of undefined
It throws error because you don't have a variable called username
or password
.
In order to solve this, you can do the following:
export class SignUpComponent implements OnInit {
myForm: FormGroup;
usernameCtrl: FormControl;
passwordCtrl: FormControl;
ngOnInit() {
this.usernameCtrl = new FormControl('username', Validators.required);
this.passwordCtrl = new FormControl('', Validators.required);
this.myForm = new FormGroup({
username: this.usernameCtrl,
password: this.passwordCtrl
});
}
}
... or using FormBuilder
:
export class SignUpComponent implements OnInit {
myForm: FormGroup;
usernameCtrl: FormControl;
passwordCtrl: FormControl;
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
this.usernameCtrl = this.formBuilder.control('username', Validators.required);
this.passwordCtrl = this.formBuilder.control('', Validators.required);
this.myForm = this.formBuilder.group({
username: this.usernameCtrl,
password: this.passwordCtrl
});
}
}
Now you can use it directly in template, like this:
<div class="alert alert-danger" *ngIf="usernameCtrl.invalid">
username is required
</div>
Also, if you prefer you can use [formControl]
instead of formControlName
:
<input
type="text"
name="username"
class="form-control"
[formControl]="usernameCtrl">
PLUNKER
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>
Plunker
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>