2016-01-31 15 views
8

Mam ten kod dla textarea, działa świetnie z ngModel i aktualizacji na żywo, jednak chciałbym my-custom-dyrektywy, aby wiedzieć, kiedy model związany do tego tekstu się zmienia.Jak wykryć zmianę modelu pola wejściowego z dyrektywy w angleular2

Jak mogę wykryć zmianę modelu dla tego obszaru tekstowego w dyrektywie my-custom?

<textarea my-custom-directive class="green" [(ngModel)]="customertext"></textarea> 

Odpowiedz

8

Aktualizacja

@Directive({ 
    selector: 'xyz', 
    host: {'(ngModelChange)': 'doSomething($event)'} 
}) 
export class Xyz { 
    doSomething(event){... } 
} 

Original

<textarea my-custom-directive class="green" [(ngModel)]="customertext" 
    (ngModelChange)="doSomething($event) "></textarea> 
[(ngModel)]="customertext" 

jest krótka forma

[ngModel]="customertext" (ngModelChange)="customertext=$event" 
+1

thankyou, ale jak stwierdził, chcę dyrektywa wykryć te zmiany, aby nie trzeba dodawać go do Kod html textarea –

+1

działa tylko wtedy, gdy wpisujesz tekst, a nie, jeśli model zmienia się z innego obszaru tekstowego powiązanego z tym samym modelem. –

+1

Jeśli "customertext" to '@Input()'? Wdrożenie 'ngModelChange (change)' w twojej dyrektywie i dodanie twojego kodu do reakcji na zmiany powinno zrobić to, co chcesz. –

5

Istnieje wiele sposobów, aby wykryć zmiany, to też zależy od ChangeDetectionStrategy określonym w Komponentu.

się być pomocny, będę uprościć odpowiedź i skupić się na reaktywnej Extensions (Rx) sposób interakcji z ngModel dyrektywy , tylko dlatego, że potężny i ma najlepszą integrację z silnikiem wykrywania zmian kątowej 2, pod względem wydajności.

Najpierw musimy podkreślić, że NgModel jest związany z wartością Elementu, a wszystkie zmiany są propagowane za pośrednictwem subskrypcji EventEmitter, którą subskrybujesz. The EventEmitter to typ Angular2, który jest obiektem Rx, który jest w zasadzie obiektem, który może "transmitować" (emitować) zdarzenia/dane, a także może reagować na dane "odebrane". Tak więc w Rx land jest obserwowalny i obserwatorem.

Warto również wspomnieć o metodzie "ngOnChanges" na ngModel, która odbiera procedurę obsługi zdarzeń zmian, ale skupimy się na podejściu Rx.

Musimy więc uzyskać dostęp do tego Obserwowalnego i zasubskrybować go, świetnie!

Aby uzyskać dostęp, używamy wtrysku zależnego, po prostu oświadczając, że chcemy, aby NgModel był w konstruktorze naszej dyrektywy.

Teraz musimy też zachować ostrożność, musimy upewnić się, że otrzymamy NgModel, bo inaczej będziemy mieć błędy.

Możemy to zrobić dyskretnie, tworząc selektor dyrektywy, które wymusza element NgModel, jak: „selektor”: „[myCustomDirective] [ngModel]”, teraz jeśli ngModel nie jest częścią elementu to won” t pasuje do selektora naszej dyrektywy.

Lub możemy hałasować i nie wychodzić cicho, zaznaczamy zastrzyk zależności jako @Opcjonalnie, a jeśli jego wartość zerowa możemy podać wyraźny wyjątek mówiąc, czego brakuje. Jeśli nie będziemy oznaczyć go jako @Opcja kątowa spowoduje wygenerowanie ogólnej wiadomości o brakującej zależności, jest ona ok, ale nie jest dobra.

Teraz przykład:

import {Directive, Optional} from 'angular2/core'; 
import {NgModel}from 'angular2/common'; 

@Directive({ 
    selector: '[myCustomDirective][ngModel]' 
}) 
export class MyCustomDirective { 
    constructor(@Optional() public model: NgModel) { 
    if (!model) 
     throw new Error ("myCustomDirective requires ngModel."); 

    // this code should be in a designated functions... 

    // register to incoming changes to the model 
    // we can also transform values..., for example take only distinct values... 
    // this.model.update.distinctUntilChanged()... 
    let subscription = this.model.update.subscribe((newValue) => { 
     // Changes happen here, do something with them... 
     // note that the value of this.model is still the old value 
     // The local parameter "newValue" holds the new value. 
    }); 

    // We can also change the value of the model: 
    this.model.update.emit('something...'); 
    } 
} 

Mam nadzieję, że pomogło.

+0

oznacza to, że pasuje tylko jeśli ngModel jest zdefiniowany w obszarze tekstowym? jak rozliczasz się w obu przypadkach. –

+0

Potrzebny jest ngModel zdefiniowany jako atrybut w elemencie DOM używanym dla własnej dyrektywy. –

+0

Pytanie dotyczy zmian w modelu, gdy istnieje ngModel. Jeśli chcesz słuchać zmian za pomocą elementu bez ngModel lub ngControl, musisz zarejestrować programy obsługi do zdarzeń Dom, takich jak zmiana, klucz itp. ... RxJs zapewnia pomocników, takich jak Observable.fromEvent ... ngModel robi to za Ciebie, ale można to zrobić bez niego ... po prostu więcej pracy –

3

Istnieją różne podejścia do wykrywania zmian w Agnular2, i zgodnie z warunkami, których używasz, będą mieć do góry i w dół. Angular umożliwia powiązanie wszystkich standardowych zdarzeń z elementami takimi jak change. więc w tym przypadku jako elementu formularza można po prostu użyć:

<textarea my-custom-directive class="green" [(ngModel)]="customertext" (change)="doSomething($event)"></textarea> 

Wydarzenie będzie rodzimy zdarzenie JavaScript, dzięki czemu można uzyskać originalEvent, target, a także uzyskać własność zmiany i jego wartość:

doSomething (e) { 
    let whatChanged = e.target.getAttribute('ng-reflect-name'); 
    let newValue = this[whatChanged]; 
    console.log(whatChanged, newValue); 
} 

Działa to szczególnie dobrze, gdy chcesz obejrzeć zmiany we wszystkich/niektórych elementach w formularzu. używanie podejścia hashowego jest również całkiem proste.

4

spróbować dodać do dyrektywy:

@HostListener('input') onInput() { 
     console.log('on input'); 
} 
+0

To jest * tylko * odpowiedź, która faktycznie odpowiada na pytanie/problem. Miałem ten sam problem, ale testowałem go za pomocą setTimeout. Próbowałem około 5 różnych podejść (łącznie z innymi odpowiedziami tutaj) bez powodzenia, ale to jest to, co wykorzystuje biblioteka Angular Material 2, aby obejść ten pseudo błąd. Dziękuję Ci!!Powinienem wskazać, że jestem na Angular 4.1, chociaż uważam, że powinno to działać dla Angular 2+. –

1

Przepuścić model (wykrywanie zmian na) jako Input() do dyrektywy i korzystania ngOnChange() jak poniżej.

import {Directive, ElementRef, Input, OnChanges} from '@angular/core'; 

@Directive({ 
    selector: '[myCustomDirective]' 
}) 
export class MyCustomDirective implements OnChanges { 

    @Input() myCustomDirective: any; 

    constructor(private el: ElementRef) {} 

    ngOnChanges(changes) { 
     if (changes.myCustomDirective) { 
      console.log('chnaged'); 
     } 
    } 

} 

Oto w jaki sposób można przekazać modelu jako wejście do dyrektywy:

<textarea [myCustomDirective]="customertext" class="green" [(ngModel)]="customertext"></textarea> 
Powiązane problemy