Reputation: 65
The problem is the error message is not getting displayed even if i leave the filed blank and move to another field. I am unable to find what i am doing wrong here. Any help would be highly appreciated. if i put a breakpoints on onFormValuesChanged() it never hits the breakpoints. i have tried moving the build part of form inside the constructor but don't have any impact. I am not sure if the form's value change event is triggered or not when field value is changed
angular ver : - 5.2.1
HTML Code
<div>
<form [formGroup]="formPersonalRecord">
<mat-input-container class="full-width-input">
<input matInput placeholder="First Name" formControlname="firstName">
<mat-error *ngIf="formErrors.firstName.required">
Please provide name.
</mat-error>
</mat-input-container>
<mat-input-container class="full-width-input">
<input matInput placeholder="Last Name" formControlname="lastName">
</mat-input-container>
<mat-input-container class="full-width-input">
<input matInput placeholder="Father's Name" formControlname="fatherName">
</mat-input-container>
<mat-input-container class="full-width-input">
<input matInput placeholder="Email" formControlname="email">
<mat-error *ngIf="formErrors.email.required">
Please provide a email name.
</mat-error>
</mat-input-container>
</form>
</div>
component.cs
import { Component, OnInit } from '@angular/core';
import { EmployeePersonalRecord } from '../employee/employee-personal-record';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { fuseAnimations } from '../../core/animations';
import { HrService } from '../hr.service';
@Component({
// tslint:disable-next-line:component-selector
selector: 'app-add-employee',
templateUrl: './add-employee.component.html',
styleUrls: ['./add-employee.component.scss'],
animations: fuseAnimations
})
export class AddEmployeeComponent implements OnInit {
employeePersonalRecord: EmployeePersonalRecord = {} as EmployeePersonalRecord;
public formPersonalRecord: FormGroup;
formErrors: any;
constructor(private builder: FormBuilder,
private service: HrService) {
}
onFormValuesChanged()
{
for ( const field in this.formErrors )
{
if ( !this.formErrors.hasOwnProperty(field) )
{
continue;
}
// Clear previous errors
this.formErrors[field] = {};
// Get the control
const control = this.formPersonalRecord.get(field);
if ( control && control.dirty && !control.valid )
{
this.formErrors[field] = control.errors;
}
}
}
ngOnInit() {
this.formPersonalRecord = this.builder.group({
firstName: ['', Validators.required],
lastName: ['', Validators.required],
email: ['', Validators.required],
fatherName: ['', Validators.required],
dateOfBirth: ['', Validators.required],
addressPermanent: ['', Validators.required],
addressCurrent: ['', Validators.required],
gender: ['', Validators.required],
maritalStatus: ['', Validators.required],
religion: ['', Validators.required],
cast: ['', Validators.required]
});
this.formErrors = {
firstName: {},
lastName: {},
email: {},
fatherName: {},
dateOfBirth: {},
addressPermanent: {},
addressCurrent: {},
gender: {},
maritalStatus: {},
religion: {},
cast: {}
};
this.formPersonalRecord.valueChanges.subscribe(() => {
this.onFormValuesChanged();
});
}
}
Upvotes: 9
Views: 58947
Reputation: 41
I think the best option is to use:
updateValueAndValidity({ onlySelf: false, emitEvent: true })
If you use onlySelf = true
, you don't need to put "markAsTouched"
in your control and works with every scenario!
Upvotes: 0
Reputation: 361
<mat-error>
content is only displayed when control is touched or when form is submitted. *ngIf
condition can be specified, it is not the issue.
To display <mat-error>
content for instance when you click on another button than the submit one, simply mark the desired control(s) as touched in the handler of the button:
onMyButtonClick() {
this.form.get('myControl').markAsTouched();
...
}
Another way to display a message under the control without any contrainst linked to Angular validity management, is to use <mat-hint>
instead of <mat-error>
Upvotes: 13
Reputation: 11
I had problem with diplaying message in mat-error( And "updateValueAndValidity" fixed this problem) In this exemplar, I show async error message in mat-error.
onSubmit() {
this.formSub = this.authenticationService
.forgotPassword(this.resetForm.get('email').value).subscribe(
next => {
}, error => {
console.log(error);
this.resetForm.get('email').updateValueAndValidity();
if (error[0] === 'USER_NOT_FOUND') {
const passwordForm = this.resetForm.get('email');
if (passwordForm) {
passwordForm.setErrors({
serverError: 'Email not found!'
});
}
}
}
)
}
Upvotes: 1
Reputation: 8953
Also, mat-error
does not display until either the control is touched (blurred), or the form is submitted.
Upvotes: 6
Reputation: 137
This might be late but I'm having the same issue and found out that I have to bind my input [formControl] to the formGroup first before getting the formControl like so :
<form [formGroup]="formPersonalRecord">
<mat-input-container class="full-width-input">
<input matInput placeholder="First Name" [formControl]="formPersonalRecord.get('firstName')">
<mat-error *ngIf="formPersonalRecord.get('firstName').hasError('required')">
Please provide name.
</mat-error>
</mat-input-container>
Upvotes: 9
Reputation: 270
I can't see any ErrorStateMatcher? You should use it.
Here is the stackblitz of the material doc, with an input that uses errorstatematcher : https://stackblitz.com/angular/voepaombnnb
Upvotes: 3
Reputation: 7221
You have a typo on formControlname. Its formControlName with uppercase N.
advice :
You should not add *ngIf on mat-error. The whole point of mat error is to avoid doing such thing.
and you should use mat-form-field component to wrap your input
so can you try simply :
<form [formGroup]="formPersonalRecord">
<mat-form-field class="full-width-input">
<input matInput placeholder="First Name" formControlName="firstName" />
<mat-error>
Please provide name.
</mat-error>
</mat-form-field>
...
Upvotes: 26