2016-05-18 17 views
5

W funkcji opisu maszynopisu poniżej "ten" nie rozwiązuje problemu z wystąpieniem EmailValidator. Jak mogę poprawić tę funkcję, aby rozwiązała poprawne wystąpienie EmailVaildator, a następnie, aby uzyskać dostęp do _registerServices?Dostęp do "tej" obietnicy wewnętrznej

class EmailValidator { 

    constructor(private _registerServices: RegisterServices) { } 

    isAvailable(c: AbstractControl): Promise<ValidationResult> { 
     let q = new Promise((resolve, reject) => { 
      this._registerServices.emailIsAvailable(antiForgeryToken(), c.value) 
       .then(result => { 
        // Need to actually check the result. 
        resolve({ "emailtaken": true }) 
       }, 
       error => { 
        // Need to communicate the server error? Probably not. 
        resolve({ "servererror": true }) 
       }); 
     }); 

     return q; 
    } 
} 
+1

Hmm. Wygląda na to, że gruba strzała powinna już to robić. Patrząc na wygenerowany kod JavaScript, wydaje się, że właściwie "ten" jest poprawny. Czy na pewno jest to problem, który widzisz? – Thilo

+0

@Thilo Od tego czasu odkryłem, że problem jest nieco ukryty i że problem był gdzie indziej. Odkryłem, jak rozwiązać ten problem, ale są pewne szczegóły dotyczące "przyczyny" wystąpienia problemu, że naprawdę doceniam wskazówki. Opublikuję moje rozwiązanie. –

Odpowiedz

7

Tracisz this, ponieważ są przechodzącą wokół isAvailableEmail jako funkcja „surowego” tutaj:

email: ['', Validators.required, this._emailValidator.isAvailableEmail] 

problem ten można rozwiązać poprzez wiązanie go this (za pomocą strzałki tłuszczu):

email: ['', Validators.required, 
    (control) => { this._emailValidator.isAvailableEmail(control) } 
] 
+0

Dzięki Thilo. Podoba mi się twoje rozwiązanie - to najmniejsza zmiana - ale pozostanie przy mnie, ponieważ jest to zgodne z tym, jak zespół Angular wydaje się implementować swoje walidatory. Zrobię twoją odpowiedź jako zaakceptowaną, ponieważ najlepiej odpowiada na oryginalne pytanie. –

+0

Należy zauważyć, że mają one "statyczne" funkcje, takie jak "Validators.required", które nie muszą być konfigurowane, oraz fabryki walidatorów, które generują funkcję walidatora przechwytującą całą ich konfigurację, np. 'Validators.minLength (8)'.Możesz zrobić coś takiego jak 'EmailValidator (registerServices)', aby wytworzyć funkcję, która przechwytuje 'registerServices' i robi to, co robi' isAvailableEmail'. – Thilo

+0

Tak więc walidator nie powinien być klasą tak bardzo jak funkcją, która tworzy inną funkcję (np. 'IsAvailableEmail'). Ta wygenerowana funkcja jest niezależna. – Thilo

1

Okazało się, że „to” Wniosek ten został niezdefiniowane, nawet jeśli to było używane w następujący sposób:

class EmailValidator { 

    constructor(private _registerServices: RegisterServices) { } 

    isAvailable(c: AbstractControl): EmailValidator { 
     return this; // 'This' is undefined! 
    } 
} 

wnoszę to ma coś wspólnego z tym, jak metoda nazwano, może przepuszczenie metoda niestatyczny gdzie oczekiwano metoda statyczna:

... 
this.registerForm = fb.group({ 
    email: ['', Validators.required, this._emailValidator.isAvailableEmail], 
    password: ['', Validators.compose([Validators.required, Validators.minLength(8)])], 
    phoneNumber: ['', Validators.required], 
    country: ['', Validators.required] 
    }); 
... 

Jeśli ktoś może zaoferować pewne wskazówki na temat tego, co jest występujący tu, że byłoby fantastycznie.

moje rozwiązanie

ja zreorganizowane mój kod i produkowane następujący:

class EmailValidator { 

    static isAvailableEmail(services: RegisterServices): (AbstractControl) => Promise<ValidationResult> { 
     let g = (c: AbstractControl) => { 
      return new Promise((resolve, reject) => { 
       services.emailIsAvailable(antiForgeryToken(), c.value) 
        .then(result => { 
         // Need to actually check the result. 
         resolve({ "emailtaken": true }) 
        }, 
        error => { 
         // Need to communicate the server error? Probably not. 
         resolve({ "servererror": true }) 
        }); 
      }); 
     }; 

     return g; 
    } 
} 

i zmieniła jego wykorzystania:

... 
this.registerForm = fb.group({ 
    email: ['', Validators.required, 
     EmailValidator.isAvailableEmail(this._registerService)], 
    password: ['', Validators.compose([Validators.required, Validators.minLength(8)])], 
    phoneNumber: ['', Validators.required], 
    country: ['', Validators.required] 
    }); 
... 

który działa poprawnie.

1

Masz problem, ponieważ podajesz wartość isAvailable, która jest funkcją. Nie wykonujesz go, tylko przekazujesz odwołanie do funkcji.

Jednym ze sposobów rozwiązania tego jest w @Thilo's answer

Innym sposobem jest przypisanie isAvailable do wyrażenia lambda zamiast funkcji. tak:

class EmailValidator { 

    constructor(private _registerServices: RegisterServices) { } 

    isAvailable = (c: AbstractControl): Promise<ValidationResult> => { 
     let q = new Promise((resolve, reject) => { 
      this._registerServices.emailIsAvailable(antiForgeryToken(), c.value) 
       .then(result => { 
        // Need to actually check the result. 
        resolve({ "emailtaken": true }) 
       }, 
       error => { 
        // Need to communicate the server error? Probably not. 
        resolve({ "servererror": true }) 
       }); 
     }); 

     return q; 
    } 
} 
0

chciałbym zaproponować, aby napisać to trochę inny

class EmailValidator { 

    constructor(private _registerServices: RegisterServices) { } 

    isAvailable(c: AbstractControl): Promise<ValidationResult> { 
     return this._registerServices.emailIsAvailable(antiForgeryToken(), c.value) 
      .then(result => { 
       // Need to actually check the result. 
       return { "emailtaken": true } 
      }) 
// shorter .then(result => ({ "emailtaken": true })) 
      .catch(error => { 
       // Need to communicate the server error? Probably not. 
       return { "servererror": true } 
      }); 
// shorter .catch(error => ({ "servererror": true })) 

     }); 

    } 
}