2016-08-01 20 views
1

Ich habe eine Gültigkeitsanweisung, die prüft, ob ein Clientschlüssel eindeutig ist. Alles scheint wie erwartet zu funktionieren, bis ich den Netzwerkverkehr überprüfe und sehe, dass er für jeden Tastendruck einen Anruf tätigt.Angular2 RC4 debounceTime ruft immer noch bei jedem Tastendruck auf

import { Directive, forwardRef, ReflectiveInjector } from '@angular/core'; 
import { AbstractControl } from '@angular/common'; 
import { FormControl, NG_VALIDATORS } from '@angular/forms'; 

import {Observable} from 'rxjs/Rx'; 

import {DomainService} from '../services/domain.service'; 

interface IRefIdValidator { 
} 

function validateRefIdFactory(domainService : DomainService) { 
    return (control: AbstractControl): Observable<IRefIdValidator> => { 

    // get the domain Id and Ref Id key 
    let domainId: number = +control.root.find('domainId').value; 
    let clientId: number = +control.root.find('clientId').value; 
    let key: string = control.value; 

    // Return an observable with null if the 
    // reference id check comes back successful 
    return new Observable((obs: any) => { 
     control 
     .valueChanges 
     .debounceTime(500) 
     .distinctUntilChanged() 
     .flatMap(value => domainService.checkDomainClientKey(domainId, clientId, key)) 
     .subscribe(
     data => { 
      obs.next(null); 
      obs.complete(); 
     }, 
     error => { 
      obs.next({ refId: true }); 
      obs.complete(); 
     } 
     ); 
    }); 
    }; 
} 

@Directive({ 
    selector: '[validateRefId][formControlName],[validateRefId][ngModel],[validateRefId][formControl]', 
    providers: [ 
    DomainService, 
    { provide: NG_VALIDATORS, useExisting: forwardRef(() => RefIdValidatorDirective), multi: true } 
    ] 
}) 
export class RefIdValidatorDirective { 
    validator: Function; 

    constructor(
    private domainService: DomainService 
    ) { 
     console.log('RefIdValidatorDirective created'); 
    this.validator = validateRefIdFactory(this.domainService); 
    } 

    validate(c: AbstractControl) { 
    return this.validator(c); 
    } 
} 

Ich verwende diese Validierung Richtlinie in einem Modell angetrieben Form:

this.domainForm = this.fb.group({ 
     clientKey: ['', Validators.required, new RefIdValidatorDirective(this.domainService).validator] 
    }); 

Wie Sie sehen können, ist dies nicht effizient ist, entweder als ich die Domain auf die Validierung von der übergeordneten Komponente am Übergang In der Richtlinie war ich jedoch nicht in der Lage, herauszufinden, wie die Dienstleistung auf andere Weise in diese Richtlinie eingefügt werden kann.

Hier ist, was meine Netzwerk-Trace aussieht, obwohl ich schnell tippe:

24?key=Test 
24?key=TestA 
24?key=TestAB 
24?key=TestABC 

Jede mögliche Hilfe bei diesem geschätzt wird.

Antwort

1

Es gibt ein Problem in Ihrem Code: Sie geben keine Observable zurück, sondern stattdessen eine Subscription, weil Sie abonnieren und zurückgeben.

Um es zu tun, ist es besser, s Subject zu erstellen, um jeden Tastenanschlag zu entprellen. Hier ist eine gute Übung, die Sie an Ihre Bedürfnisse anpassen können. Die onSearch Verfahren werden für jeden Tastendruck genannt:

import { Component, OnInit, OnDestroy } from '@angular/core'; 
import { Subscription } from 'rxjs/Subscription'; 

@Component({...}) 
export class ExampleComponent implements OnInit, OnDestroy { 
private searchTermStream = new Subject<string>(); 
private searchSubscription: Subscription; 

    ngOnInit() { 
    this.searchSubscription = this.createInputSubscriber(); 
    } 

    ngOnDestroy() { 
    this.searchTermStream.complete(); 
    } 

    onSearch(query: string): void { 
    this.searchTermStream.next(query); 
    } 

    private createInputSubscriber(): Subscription { 
    return this.searchTermStream 
     .distinctUntilChanged() 
     .debounceTime(500) 
     .subscribe((query: string) => console.log(query)); 
    } 
} 

Hier haben wir aufzuräumen auch die Speicher im ngOnDestroy Verfahren, wenn die Komponente zerstört wird.