Angular2 v.2.3 - Имейте директивный доступ к FormControl, созданному с помощью синтаксиса formControlName

Итак, я пытаюсь создать директиву, которая может манипулировать FormControl.

Похоже, что если я использую длинный синтаксис для объявления элементов управления формы в шаблоне, я могу передать элемент управления директиве, чтобы делать вещи с ним как прямую привязку @Input(); т.е. со следующим шаблоном:

<form [formGroup]="myForm">
    <input type="text" id="myText" [formControl]="myForm.controls['myText']" my-directive>
</form>

И следующая логика компонента:

@Component({
    // Properties go here.
})
class MyComponent {
    myForm: FormGroup;

    constructor(fb: FormBuilder) {
        // Constructor logic...
    }

    ngOnInit() {
        this.myForm = this.fb.group({
            "myText": [""]
        });
    }
}

Директива будет выглядеть так:

@Directive({
    selector: "[my-directive]"
})
class MyDirective {
    Input() formControl: FormControl;
}

Но если бы я использовал синтаксис formControlName в шаблоне:

<form [formGroup]="myForm">
    <input type="text" id="myText" formControlName="myText" my-directive>
</form>

Как я могу ссылаться (неявно?), сделанный FormControl в директиве?

Ответ 1

Если вы используете NgControl, ElementRef, HostListener и инъекцию конструктора, мы можем иметь директиву, применимую к элементам управления формами из реактивных форм в формах formControlName или [formControl] и даже с шаблонами:

import { Directive, ElementRef, HostListener } from "@angular/core";
import { NgControl } from "@angular/forms";

@Directive({
  selector: '[my-directive]'
})
export class MyDirective {
  constructor(private el: ElementRef, private control : NgControl) { }

  @HostListener('input',['$event']) onEvent($event){
    let valueToTransform = this.el.nativeElement.value;
    // do something with the valueToTransform
    this.control.control.setValue(valueToTransform);
  }
}

Здесь применимая демонстрация

Ответ 2

Ответ

@silentsod будет работать безупречно.

1. если вам нужно обрабатывать несколько событий, таких как нажатие клавиши вверх/вниз или любые другие события, вы можете перейти к подходу ниже. 2. Кроме того, лучше определить события в самой директиве.

import { Directive, ElementRef} from "@angular/core";
import { NgControl } from "@angular/forms";

@Directive({
  selector: '[my-directive]',
  host: {
   '(input)':'onEvent($event)',
   '(keydown.backspace)': 'onEvent($event, true)'
})
export class MyDirective {
  constructor(private el: ElementRef, private control : NgControl) { }

  public onEvent($event, someEvent){
    let valueToTransform = this.el.nativeElement.value;
    // do something with the valueToTransform
    if(someEvent) {
    //do something 
    }
    this.control.control.setValue(valueToTransform);
  }
}

В Html

<form [formGroup]="myForm">
<input type="text" id="myText" formControlName="myText" my-directive>
</form>