Digamos que estoy escribiendo una directiva de atributo personalizado para usar en elementos de formulario Angular2. Quiero poder usar mi atributo así:
<form [formGroup]="myFormGroup"> <input type="text" [myHighlight] formControlName="name" /> </form>Dentro de mi directiva tengo algo como esto:
@Directive({selector: '[myHighlight]'}) export class MyHighlightDirective { constructor (private el: ElementRef) { this.el.nativeElement.style.backgroundColor = 'yellow'; } };Pero ahora digamos que quiero hacer algo en todos los cambios en el control de entrada. Tal vez quiera aleatorizar el color en cada cambio.
El HostListener('onChange') de la guía Angular2 funciona cuando el usuario está escribiendo en el cuadro de entrada. Pero no se activa para eventos setValue que se llaman en el control de formulario, incluso con emitEvent establecido en verdadero.Los documentos de Angular en Forms dicen que setValue hará que se emita un evento valueChanges en el objeto de control de formulario. Pero no quiero tener que pasar esto a la directiva cada vez que lo uso, ya que es torpe.
¿Hay alguna otra forma de que la directiva obtenga acceso al control de formulario original, dado que solo tiene la referencia del elemento?
Angular DI al rescate!
Puede usar el sistema de Inyección de Dependencia Angular para inyectar el FormControl adjunto al elemento host de su directiva.
@Directive({selector: '[myHighlight]'}) export class MyHighlightDirective { constructor (private el: ElementRef, private formControl: FormControl) { // have fun with formControl.valueChanges ....... } };Por qué esto funciona:
Angular registra directivas en el inyector del elemento al que se adjunta la directiva. Entonces, cuando solicite una instancia de una directiva en particular, la primera búsqueda será primero en el elemento host. (Lo mismo se aplica a los componentes)
Inyectar NgControl que es tipo de FormControlName
import { NgControl } from '@angular/forms'; @Directive({selector: '[myHighlight]'}) export class MyHighlightDirective { constructor (private el: ElementRef, private formControl: NgControl) { this.el.nativeElement.style.backgroundColor = 'yellow'; .... //listen to validation status this.formControl.statusChanges.subscribe((state)=>{ ... }); } };Lo que funcionó para mí fue
@ContentChild(NgModel) public set model(model: NgModel) { ... } y puede acceder al control con model.control .