2016-12-15 7 views
12

Tak więc próbuję stworzyć dyrektywę, która może manipulować FormControl.Angular2 v.2.3 - Mam dyrektywę dostęp do FormControl utworzony przez składnię formControlName

Wygląda na to, że jeśli użyję długiej składni do deklarowania formantów formularzy w szablonie, mogę przekazać sterowanie do dyrektywy, aby zrobić z nim coś jako bezpośrednie powiązanie @Input(); czyli: Z poniższego szablonu:

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

i następnego logiki komponent:

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

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

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

Dyrektywa wyglądałby następująco:

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

Ale jeśli były przy użyciu składni formControlName w szablon zamiast:

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

W jaki sposób odwołać się do (domyślnie?) FormControl w dyrektywie?

+0

nie wiadomo, o co prosisz. Możesz zastosować dyrektywę do biernego wejścia z dowolną metodą wiązania szablonu, 'formControlName =" someName "' lub '[formControl] =" myForm.controls ['someName'] "' blisko, ponieważ mogę powiedzieć, że nie robi różnica. Jeśli zamieścisz swoją dyrektywę i dlaczego jej nie działa, to możesz uzyskać odpowiedź. – silentsod

+0

O ile mi wiadomo, składnia formControlName nie umieszcza instancji FormControl na elemencie, więc bez wyraźnego powiązania nie wiem, jak uzyskać do niego dostęp. Zmieniłem to pytanie, mam nadzieję, że jest bardziej przejrzyste. –

Odpowiedz

25

Jeśli wykorzystują NgControl, wtrysk ElementRef, HostListener i konstruktora możemy mieć dyrektywy mającymi zastosowanie do tworzenia formantów z reaktywnych form w obu formControlName lub [formControl] przykrywką a nawet opartych na szablonach formularzy:

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); 
    } 
} 

Oto applicable demo

+0

Dzięki, nie wiedziałem o NgControl. Tylko dla zrozumienia chociaż ... 1) this.control będzie oceniać do FormControlDirective, dyrektywy FormControlName, lub dyrektywy NgModel na podstawie jednak my robimy formularz? 2) this.control.control jest instancją FormControl używaną przez this.control, a dyrektywy wymienione w 1) mają to wszystko? 3) Zmiany w this.control.control będą miały zastosowanie do this.control? (np. this.control.control.markAsPristine() ustawi this.control.pristine na true?) –

+0

1) Prawidłowo, 2) Poprawnie, ale w zależności od tego, kiedy tworzysz formant, może być niezdefiniowany w konstruktorze dyrektyw (który jest dziwne, ale związane z wydarzeniami cyklu życia) 3) Tak. – silentsod

+0

Nie działa to w przypadku, gdy dyrektywa działa również jako walidator. Powoduje cykliczną zależność. –

2

@silentsod odpowiedź zadziała bezbłędnie.

1. Jeśli potrzebujesz obsługi wielu zdarzeń, takich jak naciśnięcie klawisza góra/dół lub inne zdarzenia, możesz przejść do poniższej metody.
2. Lepiej też zdefiniować zdarzenia w samej dyrektywie.

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); 
    } 
} 

w HTML

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