I created a custom form control component with implementing Control Value Accessor, and when I use it in a form in another component, I want to know if it's possible to know that the form control is invalid and touched inside of the form control itself ?
This is the component
@Component({
selector: 'custom-textbox',
templateUrl: './custom-textbox.component.html',
styleUrls: ['./custom-textbox.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => CustomTextboxComponent),
},
],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomTextboxComponent implements ControlValueAccessor, OnInit {
@Input('Label') label: string = '';
@Input('Type') type: string = 'text';
@Output('Input') input: EventEmitter<any> = new EventEmitter();
_value: string = '';
onChange = (value: any) => {};
onTouched = () => {};
touched: boolean = false;
disabled: boolean = false;
constructor(private readonly changeDetectorRef: ChangeDetectorRef) {}
ngOnInit() {
// Here I want to subscribe to something, and want to have
// some actions if the form control
// is invalid and touched. For example I will show a
// tooltip and show the reason of being invalid
}
set value(value: any) {
this._value = value;
this.onChange(value);
this.changeDetectorRef.detectChanges();
}
get value(): any {
return this._value;
}
I tried to inject NgControl like this
import { ControlValueAccessor, NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
@Component({
selector: 'custom-textbox',
templateUrl: './custom-textbox.component.html',
styleUrls: ['./custom-textbox.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => CustomTextboxComponent),
},
],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomTextboxComponent implements ControlValueAccessor, OnInit {
@Input('Label') label: string = '';
@Input('Type') type: string = 'text';
@Input('PlaceHolder') placeHolder: string = '';
@Input('ReadOnly') readOnly: boolean = false;
@Input('AutoFocus') autoFocus: boolean = false;
@Input('MaxLength') maxLength: number = 524288;
@Output('Input') input: EventEmitter<any> = new EventEmitter();
_value: string = '';
onChange = (value: any) => {};
onTouched = () => {};
touched: boolean = false;
disabled: boolean = false;
constructor(@Inject(Injector) private injector: Injector, private readonly changeDetectorRef: ChangeDetectorRef) {}
ngOnInit() {
const injectedControl = this.injector.get(NgControl);
injectedControl.control.statusChanges.subscribe((x) => {
console.log(x);
});
}
set value(value: any) {
this._value = value;
this.onChange(value);
this.changeDetectorRef.detectChanges();
}
get value(): any {
return this._value;
}
But I receive this error
ERROR NullInjectorError: R3InjectorError(AppModule)[NgControl -> NgControl]: NullInjectorError: No provider for NgControl!
at NullInjector.get (core.mjs:8893:27)
at R3Injector.get (core.mjs:9332:33)
at R3Injector.get (core.mjs:9332:33)
at ChainedInjector.get (core.mjs:13988:36)
at lookupTokenUsingModuleInjector (core.mjs:4524:39)
at getOrCreateInjectable (core.mjs:4572:12)
at NodeInjector.get (core.mjs:4866:16)
at CustomTextboxComponent.ngOnInit (custom-textbox.component.ts:45:43)
at callHookInternal (core.mjs:3940:14)
at callHook (core.mjs:3967:13)
ERROR TypeError: Cannot read properties of undefined (reading 'statusChanges')
at CustomTextboxComponent.ngOnInit (custom-textbox.component.ts:46:29)
at callHookInternal (core.mjs:3940:14)
at callHook (core.mjs:3967:13)
at callHooks (core.mjs:3922:17)
at executeInitAndCheckHooks (core.mjs:3872:9)
at selectIndexInternal (core.mjs:11756:17)
at Module.ɵɵadvance (core.mjs:11739:5)
at SampleComponent_Template (sample.component.html:24:20)
at ReactiveLViewConsumer.runInContext (core.mjs:11666:13)
at executeTemplate (core.mjs:11967:22)