Obtenga acceso a FormControl desde el componente de formulario personalizado en Angular


Tengo un componente de control de formulario personalizado en mi aplicación Angular, que implementa la interfaz ControlValueAccessor.

Sin embargo, quiero acceder a la instancia FormControl, asociada con mi componente. Estoy usando formularios reactivos con FormBuilder y proporcionando control de formulario usando el atributo formControlName.

ENTONCES, ¿cómo puedo acceder a la instancia FormControl desde el interior de mi componente de formulario personalizado?

Author: Slava Fomin II, 2017-06-24

3 answers

Esta solución nació de la discusión en el repositorio Angular. Por favor, asegúrese de leerlo o incluso mejor participar si usted está interesado en este problema.


He estudiado el código de la directiva FormControlName y me ha inspirado a escribir la siguiente solución:

@Component({
  selector: 'my-custom-form-component',
  templateUrl: './custom-form-component.html',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: CustomFormComponent,
    multi: true
  }]
})
export class CustomFormComponent implements ControlValueAccessor, OnInit {

  @Input() formControlName: string;

  private control: AbstractControl;


  constructor (
    @Optional() @Host() @SkipSelf()
    private controlContainer: ControlContainer
  ) {
  }


  ngOnInit () {

    if (this.controlContainer) {
      if (this.formControlName) {
        this.control = this.controlContainer.control.get(this.formControlName);
      } else {
        console.warn('Missing FormControlName directive from host element of the component');
      }
    } else {
      console.warn('Can\'t find parent FormGroup directive');
    }

  }

}

Estoy inyectando el padre FormGroup al componente y luego obtengo el FormControl específico de él usando el nombre de control obtenido a través de la unión formControlName.

Sin embargo, tenga en cuenta, que esta solución está diseñada específicamente para el caso de uso en el que se utiliza la directiva FormControlName en el elemento host. No funcionará en otros casos. Para esto tendrá que añadir un poco de lógica adicional. Si usted piensa, que esto debe ser abordado por Angular, asegúrese de visitar la discusión.

 25
Author: Slava Fomin II,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-13 06:31:34

Usar formControlName como parámetro de entrada no funciona cuando se enlaza a través de la directiva [formControl].

Aquí hay una solución que funciona en ambos sentidos sin ningún parámetro de entrada.

export class MyComponent implements AfterViewInit {

  private control: FormControl;

  constructor(
    private injector: Injector,
  ) { }

  // The form control is only set after initialization
  ngAfterViewInit(): void {
    const ngControl: NgControl = this.injector.get(NgControl, null);
    if (ngControl) {
      this.control = ngControl.control as FormControl;
    } else {
      // Component is missing form control binding
    }
  }
}
 7
Author: Randy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-01 21:01:37

Como @Ritesh ya ha escrito en el comentario, puede pasar el control de formulario como un enlace de entrada:

<my-custom-form-component [control]="myForm.get('myField')" formControlName="myField">
</my-custom-form-component>

Y luego puede obtener una instancia de control de formulario dentro de su componente de formulario personalizado de la siguiente manera:

@Input() control: FormControl;
 3
Author: Yuri Beliakov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-31 22:23:24