I have created a custom input with ControlValueAccessor
I can use it in formControl and it works fine. Now I would like to know when the form control is considered invalid to display a red border on the input inside my custom component.
Here is my custom input:
@Component({
selector: 'app-input',
templateUrl: './input.component.html',
styleUrls: ['./input.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: InputComponent,
},
],
})
export class InputComponent implements ControlValueAccessor {
group = new FormGroup({
input: new FormControl(''),
});
touched: boolean = false;
// The id used for the html
id!: number;
// The label of the html input
@Input() label: string = '';
@Input() type: string = 'text';
// The method called when the input is touched
onTouched = () => {};
constructor() {
this.id = Math.floor(Math.random() * 100);
}
/**
* The setter of the input value
* @param value
*/
writeValue(value: string): void {
this.input.setValue(value);
}
/**
* Function to subscribe to changes
* @param fn
*/
registerOnChange(fn: any): void {
this.input.valueChanges.subscribe((value) => {
fn(value);
});
}
/**
* Function to subscribe when the input is touched
* @param fn
*/
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
/**
* fucntion called to define the input as touched
*/
markAsTouched() {
if (!this.touched) {
this.onTouched();
this.touched = true;
}
}
/**
*
* @param isDisabled
*/
setDisabledState?(isDisabled: boolean): void {
if (isDisabled) {
this.input.disable();
} else {
this.input.enable();
}
}
get input() {
return this.group.get('input') as FormControl;
}
}
Then I can use it like that.
<app-input
formControlName="email"
label="Email"
></app-input>
If my email form control is invalid (because it's not a valid email for example), then there is some class added on my component inside the DOM.
Is there a way to get the validity status inside the TS component ?
CodePudding user response:
Instead of providing your value accessor in the decorator with the providers
property, use this :
constructor(
@Optional() @Self() private ngControl: NgControl
) {
// ...
if (this.ngControl) this.ngControl.valueAccessor = this;
}
It does the same thing. But what it does MORE, in your case, is to give you access to the native form control with this.ngControl.control
.
This means you can get the status of the control at any given point, for instance, you can make this :
get status() {
return this.ngControl.control.status; // "INVALID", "VALID", "PENDING"
}
CodePudding user response:
you can inject the Injector
like this:
export class InputComponent implements OnInit , ControlValueAccessor {
_control!: NgControl;
constructor(@Inject(INJECTOR) private injector: Injector) { }
ngOnInit(): void {
this._control = this.injector.get(NgControl);
}
and then you can access all control methods - for example:
get isError() {
return this._control.control?.invalid;
}