I am creating a custom form control component (email) that contains an input field, I forward the value of the input field (done correctly) but also want to forward its errors.
Using the following code I successfully pass the field's errors when the input changes but it does not pick up the initial errors correctly.
For example this email field will still report errors = {'required':true} even after the view is fully loaded and a value of '[email protected]' is passed to it. Starting to type in the field and it will pass the errors correctly.
So my question is, how can I pass the errors after the initial load of data?
note: the problem is resolved by running this.propagateChange(this.value); in DoCheck lifecycle but I don't like it, I need something that is more efficient but no other hook seems to do the trick.
Here is the example:
import {Component, forwardRef, Input, ViewChild} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormControl, NgModel} from '@angular/forms';
@Component({
selector: 'input-email',
template:`<form-group
[errors]="{'required':'Email required', 'email':'Invalid email format'}"
[info]="'Email*'"
>
<input
type = "email"
name = "email"
class = "form-control"
[(ngModel)] = "value"
placeholder = "{{placeholder}}"
(input)="onChange()"
email
required
#f = "ngModel"
>
{{f.errors | json}}
</form-group>`,
styleUrls: ['./email.component.css'],
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputEmailComponent), multi: true },
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputEmailComponent), multi: true }
]
})
export class InputEmailComponent implements ControlValueAccessor {
value:String = null;
@ViewChild('f') f:NgModel;
@Input()
placeholder:String = "Email";
propagateChange:any = (val) => {};
constructor() {}
onChange(){
this.propagateChange(this.value);
}
/**
* Write a passed NgValue value to the element.
*/
writeValue(value) {
if (value && this.value != value) {
this.value = value;
}
}
/**
* Set the function to be called
* when the control receives a change event.
* registers 'fn' that will be fired when changes are made
* this is how we emit the changes back to the form
*/
registerOnChange(fn) {
this.propagateChange = fn;
}
/**
* Set the function to be called
* when the control receives a touch event.
*/
registerOnTouched(fn) {}
/**
* Set the function to be called
* to validate if input has errors.
*/
validate(c: FormControl):any {
console.log('validate email');
return this.f.errors;
}
}