Form with Custom Component does not recognize control

前端 未结 2 1920
暗喜
暗喜 2021-01-17 01:19

I am using a custom component (custom-text) which has the below code

    @Component({
      selector: \'custom-text, [custom-text]\',
      templateUrl: \'./         


        
2条回答
  •  攒了一身酷
    2021-01-17 01:52

    I leave in stackblitz the most simple custom form control based in material input.

    As you see implements ControlValueAccessor, that's has the functions:

    onChange:any; //declare this function to indicate in any time that you change the value
    onTouched:any; //declare this function to indicate in any time that your compoment is touched
    
     writeValue(value: any[]|any): void {
        this.value=value;
      }
    
      registerOnChange(fn: any): void {
        this.onChange = fn;
      }
    
      registerOnTouched(fn: any): void {
        this.onTouched = fn;
      }
    
      setDisabledState(isDisabled: boolean): void {
        this.disabled=isDisabled
      }
    

    And a provider like

       {
          provide: NG_VALUE_ACCESSOR,
          useExisting: forwardRef(() => CustomMat),
          multi: true
        }
    

    If you want to make a validation inside the component, you need add a new provider

       {
          provide: NG_VALIDATORS,
          useExisting: forwardRef(() => CustomMat),
          multi: true,
        }
    

    And create the function validate

    validate(control: AbstractControl): ValidationErrors | null{
          //your logic here
          return null;
      }
    

    I used this two more functions:

    setValue(value: any){
        this.value=value;
        this.onChange(value);
    
      }
      focusOut()
      {
        this.onTouched()
      }
    

    To call a change and a touched functions

    Updated 01.04.20 well, the problem of this custom material input is that the error can not see reflected in the input, so we are going to make some change

    The idea is add a customError matcher

    export class CustomFieldErrorMatcher implements ErrorStateMatcher {
      constructor(private customControl: AbstractControl,private errors:any) { }
    
      isErrorState(control: AbstractControl | null, form: FormGroupDirective | NgForm | null): boolean {
        return this.customControl && this.customControl.touched && this.customControl.invalid;
      }
    }
    

    That's our inner input is invalid if the control is invalid. Well, are a dificult that is know what is the this "control". For this, in ngAfterViewInit we inject the NgControl, and this ngControl will be our control, puff

    ngAfterViewInit(): void {
        const ngControl: NgControl = this.injector.get(NgControl, null);
        if (ngControl) {
          setTimeout(() => {
            this.control = ngControl.control;
             this.matcher = new CustomFieldErrorMatcher(this.control,null);
          })
        }
      }
    

    At least add this matcher

      
    

    You can see in this stackblitz

提交回复
热议问题