I am new to angular let say, i have reactive form like follow
ngOnInit() {
this.registerFormGroup = this.formBuilder.group({
email: [ '', Validatorspose([Validators.required, Validators.email])],
password: this.formBuilder.group({
first: [ '', Validators.required ],
second: [ '', Validators.required, ]
})
});
}
and my angular template looks like follow
<div class="container">
<form [formGroup]="registerFormGroup"
(ngFormSubmit)="registerUser(registerFormGroup.value)" novalidate>
<div class="form-group" >
<label for="email">Email</label>
<input type="email" formControlName="email" placeholder="Enter Email"
class="form-control">
</div>
<div *ngIf="!registerFormGroup.get('password').get('first').valid"
class="alert alert-danger">
</div>
<div class="form-group text-center">
<button type="submit" class="btn btn-success btn-lg"
[disabled]="!registerFormGroup.valid">Submit</button>
</div>
For example, email field has two validations such as required
and email
type validate so depends upon the error I have to display error message so in my template am using like
<div *ngIf="!registerFormGroup.get('email').valid && (registerFormGroup.get('email').touched)"
class="alert alert-danger">
</div>
Instead of adding same registerFormGroup.get('email')
again and again i trying to create template expression like #emailForm="registerFormGroup.get('email')"
in
<input type="email" formControlName="email" placeholder="Enter Email" class="form-control" #emailForm="registerFormGroup.get('email')">
so that i can use use like
<div *ngIf="!emailForm.valid" class="alert alert-danger">
</div>
but i am getting error like
piler.es5.js:1690 Uncaught Error: Template parse errors: There is no directive with "exportAs" set to "registerFormGroup.get('email')" ("l> ]#emailForm="registerFormGroup.get('email')">
what mistake i made??
I am new to angular let say, i have reactive form like follow
ngOnInit() {
this.registerFormGroup = this.formBuilder.group({
email: [ '', Validators.pose([Validators.required, Validators.email])],
password: this.formBuilder.group({
first: [ '', Validators.required ],
second: [ '', Validators.required, ]
})
});
}
and my angular template looks like follow
<div class="container">
<form [formGroup]="registerFormGroup"
(ngFormSubmit)="registerUser(registerFormGroup.value)" novalidate>
<div class="form-group" >
<label for="email">Email</label>
<input type="email" formControlName="email" placeholder="Enter Email"
class="form-control">
</div>
<div *ngIf="!registerFormGroup.get('password').get('first').valid"
class="alert alert-danger">
</div>
<div class="form-group text-center">
<button type="submit" class="btn btn-success btn-lg"
[disabled]="!registerFormGroup.valid">Submit</button>
</div>
For example, email field has two validations such as required
and email
type validate so depends upon the error I have to display error message so in my template am using like
<div *ngIf="!registerFormGroup.get('email').valid && (registerFormGroup.get('email').touched)"
class="alert alert-danger">
</div>
Instead of adding same registerFormGroup.get('email')
again and again i trying to create template expression like #emailForm="registerFormGroup.get('email')"
in
<input type="email" formControlName="email" placeholder="Enter Email" class="form-control" #emailForm="registerFormGroup.get('email')">
so that i can use use like
<div *ngIf="!emailForm.valid" class="alert alert-danger">
</div>
but i am getting error like
piler.es5.js:1690 Uncaught Error: Template parse errors: There is no directive with "exportAs" set to "registerFormGroup.get('email')" ("l> ]#emailForm="registerFormGroup.get('email')">
what mistake i made??
Share Improve this question edited Sep 9, 2017 at 5:20 Rohan Fating 2,13316 silver badges24 bronze badges asked Sep 9, 2017 at 4:40 HariHari 1,6231 gold badge25 silver badges47 bronze badges 7- Template variables are not ordinary variables. They can't hold arbitrary values like that. – Harry Ninh Commented Sep 9, 2017 at 4:52
- 1 check this one medium./codingthesmartway--blog/… – Robert Commented Sep 9, 2017 at 4:54
- @HarryNinh thanks for the info, i thought of using like #name="ngModel" in template driven forms – Hari Commented Sep 9, 2017 at 4:59
-
1
@Robert that link is for template driven where the assign
#title="ngModel"
but in reactive forms we cant use ngModel right . – Hari Commented Sep 9, 2017 at 5:02 - both are similar, refer this one coursetro./posts/code/66/Angular-4-Reactive-Forms-Tutorial – Robert Commented Sep 9, 2017 at 5:11
6 Answers
Reset to default 3You can create mon function to access form like below:
validateFormControl(controName: string) {
let control = registerFormGroup.get(controName);
return control.invalid && control.touched;
}
In Templete use this call wherever you need, you just need to pass your control name in function, you can modify this function as per your need as well and you do not need to use form.get
all the time. This makes your template more cleaner and performance efficient.
<div *ngIf="validateFormControl('email')"
class="alert alert-danger">
error message
</div>
<div *ngIf="validateFormControl('password')"
class="alert alert-danger">
error message
</div>
Create a method on the ponent that returns if the form is valid or not and return it in the ponent
checkError(){ // either you can pass the form from the template or use the ponent for decleration
return registerFormGroup.get('email').valid;
}
In the template call
<div *ngIf="checkError()" class="alert alert-danger">
// Always make sure not to use controls in the template it will result in AOT pilation error
</div>
try this :
ponent.html
<div class="container">
<form [formGroup]="registerFormGroup"
(ngFormSubmit)="registerUser(registerFormGroup.value)" novalidate>
<div class="form-group" [ngClass]="{'has-error':!registerFormGroup.controls['email'].valid}">
<label for="email">Email</label>
<input type="email" formControlName="email" placeholder="Enter Email"
class="form-control">
<p class="alert alert-danger" *ngIf="registerFormGroup.controls['email'].dirty && !registerFormGroup.controls['email'].valid">Invalid email address</p>
</div>
<div class="form-group text-center">
<button type="submit" class="btn btn-primary" [disabled]="!registerFormGroup.valid">Submit</button>
</div>
</form>
</div>
ponent.ts
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
export class AppComponent implements OnInit {
registerFormGroup: any;
constructor(
private formBuilder: FormBuilder
) {}
ngOnInit() {
this.registerFormGroup = this.formBuilder.group({
email: [null , Validators.pose([Validators.required, Validators.email])]
});
}
}
Angular team strongly discourage from using functions outputs in templates due to change detection strategy. You might be interested in following solution, using ngForm
directive:
<div class="container">
<form [formGroup]="registerFormGroup"
(ngFormSubmit)="registerUser(registerFormGroup.value)" novalidate>
<div class="form-group" >
<label for="email">Email</label>
<input type="email" formControlName="email" placeholder="Enter Email "
class="form-control" #email="ngForm">
</div>
<div *ngIf="email.invalid"
class="alert alert-danger">
</div>
It's still a hush to copy-paste it in template, but at least you might have direct reference to control via it's template variable. I personally go with controller getter function still, but I'm posting this answer for sake of answer pleteness.
Although I agree with the accepted answer (you should have a dedicated method in your form ponent that will encapsulate the validation process) sometimes you need a quick check in the template:
The trick is to expose the formGroup from your ponent and use it like so:
Template:
<input id="name" class="form-control"
formControlName="name" required
[class.is-invalid]="
f.name.invalid &&
(f.name.touched ||
f.name.touched.dirty)">
Component:
//easily access your form fields
get f() { return this.checkoutForm.controls; }
I was also looking for a more elegant solution than calling form.get multiple times. Here is what I e up with using ngif
<div class="col-sm-6" *ngIf="form.get('sponsor') as sponsor">
<input type="text" formControlName="sponsor" id="sponsor" class="form-control" name="sponsor"
[class.is-invalid]="sponsor.errors && sponsor.touched">
</div>
using the as feature on ngIf to create a template variable