setValidators in custom control without from reference in Angular

£可爱£侵袭症+ 提交于 2019-12-10 09:25:17

问题


i have created a custom input control. I don't want to create any custom validation. I want to use default required, minLength, maxLength etc.I know i can do like this

this.form.controls["firstName"].setValidators([Validators.minLength(1), Validators.maxLength(30)]);

but i can't send form reference from parent component. How can i use setValidator inside textbox component.

// input-box.component.ts    
    import { Component, Input, forwardRef } from '@angular/core';
    import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';


    @Component({
      selector: 'app-input-box',
      template:`<label >{{inputdata.label}}</label><br>
      <input type="text" required #textBox [value]="textValue" (keyup)="onChange($event.target.value)" />`,
      styleUrls: ['./input-box.component.less'],
      providers: [
        {
          provide: NG_VALUE_ACCESSOR,
          useExisting: forwardRef(() => InputBoxComponent),
          multi: true
        },
        /*{
          provide: NG_VALIDATORS,
          useExisting: forwardRef(() => InputBoxComponent),
          multi: true,
        }*/]
    })
    export class InputBoxComponent implements ControlValueAccessor {
      @Input() inputdata: any;
      private textValue: any = '';

      onChange(value) {
        this.textValue = value;
        this.propagrateChange(value);
      }

      private propagrateChange = (_: any) => { };

      writeValue(value: any) {
        if (this.inputdata.value) {
          this.textValue = this.inputdata.value;
          this.propagrateChange(this.inputdata.value);
        }

      }

      registerOnChange(fn: (value: any) => any) {
        this.propagrateChange = fn;
      }


      registerOnTouched() { }
    }

use in different component

<app-input-box  name="textBoxParent_{{index}}"  [inputdata]="goaldata"  ngModel ></app-input-box>

回答1:


If you want to access the FormControl inside a class that wants to implement the ControlValueAccessor you have to change your usual implementation. You cannot register the class as ControlValueAccessor in the providers array AND inject the FormControl in the constructor. Because the FormControl will try to inject your class, and you will try to inject the control, which will create a circular dependency.

So the changes you need to make are as follows:

  1. Remove NG_VALUE_ACCESSOR and NG_VALIDATORS from the providers array.
  2. Inject NgControl in the constructor and set the control's ControlValueAccessor and Validators.

    constructor(@Self() ngControl: NgControl) { 
       ngControl.valueAccessor = this;
       ngControl.setValidators([Validators.minLength(1), Validators.maxLength(30)]
       ngControl.updateValueAndValidity()
    }
    

If you want to keep the validators specified by the consumer of your custom form component you need to modify the constructor to this:

constructor(@Self() ngControl: NgControl) { 
  const control = ngControl.control;

  let myValidators = [Validators.required, Validators.minLength(5)];
  let validators = control.validator
  ? [control.validator, ...myValidators]
  : myValidators;

  control.setValidators(validators)
  control.updateValueAndValidity();
}

Check out the whole process explained by Kara Erickson (angular core) at AngularConnect 2017. Link



来源:https://stackoverflow.com/questions/49577602/setvalidators-in-custom-control-without-from-reference-in-angular

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!