Search code examples
angularangular-materialangular-forms

Angular ControlValueAccessor and markAsTouched


I'm using angular 9 with Angular Material and I have a custom control by implementing the ControlValueAccessor interface. Everything is working fine.

In all my submit buttons when the form is not valid, I call formGroup.markAllAsTouched because all the angular material fields become in red. In this way the user can better understand which controls are not valid.

I need to implement the same behavior with my custom control. How to do that?

I've created a stackblitz project in order to better understand the situation here


Solution

  • Another chance is to use the following approach

    Custom control code

    @Component({
      selector: 'cvl-advertising-type',
      templateUrl: './advertising-type.component.html',
      styleUrls: ['./advertising-type.component.scss'],
    })
    export class AdvertisingTypeComponent implements OnInit, ControlValueAccessor {
      advertisingTypes: ReadonlyArray<LookupModel>;
    
      onChange = (value: number) => {
      };
      onTouched = () => {
      };
    
      constructor(private lookupService: LookupService,
                  @Self() public controlDir: NgControl) {
        controlDir.valueAccessor = this;
      }
    
      ngOnInit(): void {
        this.advertisingTypes = this.lookupService.advertisingTypes;
      }
    
      registerOnChange(fn: (value: number) => void): void {
        this.controlDir.control.valueChanges.subscribe(fn);
        this.onChange = fn;
      }
    
      writeValue(value: number): void {
        this.controlDir.control.setValue(value);
        this.onChange(value);
      }
    
      registerOnTouched(fn: any): void {
        this.onTouched = fn;
      }
    
      setDisabledState(isDisabled: boolean): void {
        if (isDisabled) {
          this.controlDir.control.disable();
        } else {
          this.controlDir.control.enable();
        }
      }
    }
    

    and parent html form

    <cvl-advertising-type [formControl]="form.controls.advertisingType"></cvl-advertising-type>
    

    I've found this solution after viewing this video

    Last but not least problem is that I'm not understanding how to test it with a shallow test because I've the following error

    Error: NodeInjector: NOT_FOUND [NgControl]