2016-08-30 1 views
2

Ich habe ein Problem mit der folgenden Prüffunktion:Ausgabe mit Prüffunktion auf Formularsteuerung nicht Einstellung Fehlerobjekt

export function validateEmailKnownFactory(userAccountService: UserAccountService): {[key: string]: any} { 
    return (control: AbstractControl) => { 
    return control 
     .valueChanges 
     .debounceTime(1000) 
     .switchMap(value => userAccountService.checkAvailability(value)) 
     .map(res => { 
     if (res.json() === false) { 
      return null; 
     } 
     //Control flow does get through here 
     return {emailKnownValidator: {unknown: true}}; 
     }); 
    }; 
} 

Es ist nicht das Fehlerobjekt Einstellung (dh {emailKnownValidator: {unknown: true}}) auf dem Formular Kontrolle, aber der Steuerfluss kommt durch den richtigen Ort.

Nun, wenn ich ersetzen die obige Funktion mit dem folgenden:

export function validateEmailKnownFactory(userAccountService: UserAccountService): {[key: string]: any} { 
    return (control: AbstractControl) => { 
    return userAccountService.checkAvailability(control.value) 
     .map(res => { 
     if (res.json() === false) { 
      return null; 
     } 
     return {emailKnownValidator: {unknown: true}}; 
     }); 
    }; 
} 

das Fehlerobjekt wird fein auf dem Formular Kontrolle und die Anwendung verhält sich wie erwartet.

Beachten Sie den Unterschied: Ich erhalte die Observable von control.valueChanges und ich rufe debounceTime auf sie, während die andere Funktion direkt nur checkAvailability nennen.

Der Vollständigkeit halber ist hier die checkAvailability Methode:

checkAvailability(email: string) { 
    let body = 'email=' + email; 
    return this.http.get(this.urls.USER_ACCOUNT.EMAIL_AVAILABLE + body); 
    } 

Antwort

2

Asynchronous Validator Funktionen in Angular 2 zurückkehren kann entweder eine Promise oder eine Observable. Wenn ein Observable zurückgegeben wird, muss es abgeschlossen werden - als Angular converts the Observable to a Promise. Das heißt, die Observable wird verwendet, so dass die Validierung asynchron sein kann - nicht so, dass der Validator einen Strom von Ergebnissen liefern kann.

Die Observable bestehend aus valueChanges in Ihrem ersten Validator nicht abgeschlossen - wie valueChanges pumpt ständig Änderungen aus. Das bedeutet, dass Promise nicht aufgelöst wird und es kein Validierungsergebnis gibt, das auf das Steuerelement angewendet werden kann. (Beachten Sie, dass Angular Ihre Validierungsfunktion für jede Änderung des Werts des Steuerelements aufruft und dass für jeden Aufruf ein Observable Composer und Subskribiert wird, sodass checkAvailability für jede Änderung aufgerufen wird. Der Operator debounceTime wird das Verhalten nicht beeinflussen Sie scheinen zu wollen.)

Die Observable zurückgegeben von der checkAvailability Funktion ist abgeschlossen, so dass Ihre zweite Validator-Funktion funktioniert.

+0

Danke für diese detaillierte Erklärung. Es gibt einen letzten Punkt, den ich Ihnen dankbar wäre, um zu verdeutlichen: Wollen Sie sagen, dass "debounceTime" nicht die gewünschte Wirkung erzielen wird, weil das Observable "* abonniert *" ist? – balteo

+0

Die Umwandlung in ein 'Versprechen' wird ein Abonnement beinhalten, aber das ist nicht wirklich, wo das Problem liegt. Es ist diese Tatsache, dass jeder Aufruf an den Validator seinen eigenen zusammengesetzten "Observable" zurückgibt, der "valueChanges" zu dem HTTP-basierten "Observable" von "checkAvailability" kettet, so dass jeder Aufruf immer die letzte Änderung in checkAvailability sehen wird '. Sie könnten 'debounceTime' verwenden, um ein' Observable' zu ​​komponieren, um den gewünschten Effekt zu erzielen, aber Sie können es nicht innerhalb des Validators erstellen, da dies dazu führt, dass jeder Aufruf ein separates 'Observable' erstellt. – cartant

+0

Ich hoffe, das macht Sinn. Es wird ein bisschen spät, hier. – cartant

Verwandte Themen