Reputation: 14771
I am learning Angular 5 with TypeScript. I am completely new to it. I am now trying to construct a form and validating it. But it is not working properly.
This is my component:
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss'],
animations: [routerTransition()]
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
errors = [];
constructor(private fb: FormBuilder, public router: Router, private globals: GlobalsService, private http: Http) {
}
ngOnInit() {
this.loginForm = new FormGroup({
email: new FormControl("", Validators.required),
password: new FormControl("")
});
}
onLoggedin(formData) {
alert("Submit form");
}
}
As you can see I am setting "required" validation attribute on the email field. This is my html.
<div class="login-page" [@routerTransition]>
<div class="row justify-content-md-center">
<div class="col-md-4">
<img src="assets/images/logo.png" width="150px" class="user-avatar" />
<h1>Yo Cash Flow</h1>
<div class="alert alert-danger" *ngFor="let error of errors">
<strong>{{ error.msg }}</strong>
</div>
<form [formGroup]="loginForm" role="form" (ngSubmit)="onLoggedin(loginForm.value)">
<div class="form-content">
<div class="form-group">
<input type="text" name="email" formControlName="email" class="form-control input-underline input-lg" placeholder="Email">
<div *ngIf="loginForm.controls['email'].errors.required" class="text-danger">Email is required</div>
</div>
</div>
<button type="submit" class="btn rounded-btn"> Log in </button>
<a class="btn rounded-btn" [routerLink]="['/signup']">Sign up</a>
</form>
</div>
</div>
</div>
As you can see I am trying to show the error individually. I mean for "required" attribute, I am retrieving the error message like this errors.required. But it is not working. But when I tried to use "valid" like below, it is working.
loginForm.controls['email'].invalid
But I want to retrieve the error individually because I want to show the different message for the different error. How can I fix this? Why it is not working when I use loginForm.controls["email"].errors.required
? What is the correct way of showing the different message for the different validation rule?
Upvotes: 5
Views: 28839
Reputation: 1
In Angular docs exists two ways to validate forms, try to use the "correct" way for your expected result:
I suggest learning Reactive Forms (Template-driven gets easier after learning it).
In Reactive Forms:
<form [formGroup]="loginForm" (ngSubmit)="onLoggedin(loginForm.value)">
<div>
<input type="text" name="email" formControlName="email" placeholder="Email"/>
<div *ngIf="email.errors?.required && email.touched">Email is required</div>
<div *ngIf="email.errors?.pattern && email.touched">Invalid Pattern</div>
</div>
<div>
<button type="submit"[disabled]="!loginForm.valid">Login</button>
</div>
</form>
export class AppComponent implements OnInit {
loginForm: FormGroup;
errors = [];
email: FormControl = new FormControl('', [
Validators.required,
Validators.pattern('^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$'),
]);
password: FormControl = new FormControl('');
ngOnInit() {
this.loginForm = new FormGroup({
email: this.email,
password: this.password,
});
}
onLoggedin(formData) {
alert('Submit form');
}
Notes:
I declare FormControls at root of component to directly bind in html file;
In validator messages "email.errors?.required" I use ? to allow "email.errors"(when email is valid) be null and not throw error;.
Upvotes: 0
Reputation: 11
I have just spent a couple of hours trying to debug this problem in my project, the problem in my case turned out to be using:
<input type="checkbox" formControlName="testing" />
instead of:
<input type="checkbox" [formControl]="form.controls['testing']" />
In my case the FormControl "testing" is dynamically added using form.AddControl() - the second way of performing the name binding also binds the model to the input.
Hoping this can help someone with this issue!
Upvotes: 1
Reputation: 439
You must use (loginForm.valid)
inside the *ngIf
or [disabled] property of the button. This automatically checks whether the form is validated or not from the ts file.
Moreover, inside the ts file, you can write your validations:
new FormControl('',[Validators.required])
like this.
Upvotes: 0
Reputation: 18271
You can use the errors
property, like so:
loginForm.controls['email'].errors
If there are no errors, it will return null, otherwise it will return an object like so:
{ required : true }
Then you simply need to create a function that will return a human readable error message, like so:
getErrorMessage(controlName, displayName) {
let result = "";
let errors = loginForm.controls[controlName].errors;
if (errors.required) {
result += (displayName + " is required.");
}
if (errors.whatever) {
result += "Whatever you like";
}
return result;
}
Upvotes: 3