Knowing a custom form control is invalid and touched inside of the component itself?

118 views Asked by At

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)
0

There are 0 answers