working on angular 5 form validation. All is working fine except error message are displaying movement page load which is fine only if loaded data doesn't complaints with validation but not for untouched tabs, i.e. empty textbox.
I want to show error message only when user start typing except if loaded data not valid. surprisingly, minLength and maxLength behaving as I want, not sure about others
<div *ngIf="form.controls[question.key].invalid && (form.controls[question.key].invalid || form.controls[question.key].touched)" class="alert alert-danger">
<div *ngIf="form.controls[question.key].hasError('required')">
Name is required.
</div>
<div *ngIf="form.controls[question.key].hasError('email')">
Email Format is Incorrect.
</div>
<div *ngIf="form.controls[question.key].hasError('minlength')">
Minimum Length Required.
</div>
<div *ngIf="form.controls[question.key].hasError('maxlength')">
Maximum Length Required.
</div>
<div *ngIf="form.controls[question.key].hasError('postCode')">
PostCode Incorrect.
</div>
</div>
@Injectable()
export class QuestionControlService {
private validations: ValidatorFn[] = [];
constructor() {
}
toFormGroup(questions: QuestionBase<any>[]) {
let group: any = {};
questions.forEach(question => {
this.validations = [];
debugger;
for (var key in question.validations) {
this.mapValidation(question.validations[key].title, question.validations[key].value);
}
group[question.key] = new FormControl(question.value || '', this.validations);
});
return new FormGroup(group);
}
mapValidation(validationTitle: string, validationValue: string) {
if (validationTitle != null) {
if (validationTitle == "minLength") {
this.validations.push(Validators.minLength(parseInt(validationValue)));
} else if (validationTitle == "maxLength") {
this.validations.push(Validators.maxLength(parseInt(validationValue)));
} else if (validationTitle == "required" && validationValue == "true") {
this.validations.push(Validators.required)
} else if (validationTitle == "emailType" && validationValue == "true") {
this.validations.push(Validators.email);
} else if (validationTitle == "postCodeType" && validationValue == "true") {
this.validations.push(postCodeValidator);
}
}
}
}
//Custom Validation
//-----------------
function postCodeValidator(control: FormControl) {
let givenPostCode = control.value;
let UKPostCodePattern = /^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))\s?[0-9][A-Za-z]{2})$/;
var isUKPostCodeValid = UKPostCodePattern.test(givenPostCode);
if (!isUKPostCodeValid) {
return {
postCode: {
required: "UK Valid PostCode",
provided: givenPostCode
}
}
}
return null;
}
This makes your error messages to wait untill interaction is done with input
form.controls[question.key].touched
You have to either exclude condition or add another one that will take fact that data has been loaded into consideration.
it can be like this
form.controls[question.key].touched || isDataLoaded
so errors will appear if form is invalid AND (input has been touched OR data has been loaded from somewhere)
You can also use directive to make input field initially touched,thus validation will apply. You will have to modify it for conditional execution i guess.
https://stackblitz.com/edit/angular-urqles-xbvkpn?file=app/input-overview-example.html