Reputation: 5432
In the typescript function below, 'this' doesn't resolve to the instance of EmailValidator. How can I correct this function so it resolves to the correct instance of EmailVaildator and in turn, so that I can access _registerServices?
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;
}
}
Upvotes: 8
Views: 8220
Reputation: 79
I would offer to write it a bit different
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 }))
});
}
}
Upvotes: 0
Reputation: 16540
You have the problem because you are passing the value of isAvailable
which is a function. You are not executing it, you are just passing the reference to the function.
One way to solve it is as in @Thilo's answer
Another way is to assign isAvailable
to a lambda expression instead of a function. like this:
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;
}
}
Upvotes: 1
Reputation: 262464
You are losing this
, because you are passing around the isAvailableEmail
as a "raw" function here:
email: ['', Validators.required, this._emailValidator.isAvailableEmail]
You can fix this by binding it to this
(using the fat arrow):
email: ['', Validators.required,
(control) => { this._emailValidator.isAvailableEmail(control) }
]
Upvotes: 9
Reputation: 5432
It turned out that the 'this' reference was undefined even if it was used as follows:
class EmailValidator {
constructor(private _registerServices: RegisterServices) { }
isAvailable(c: AbstractControl): EmailValidator {
return this; // 'This' is undefined!
}
}
I gather this has something to do with how the method was called, perhaps passing a non-static method where a static method was expected:
...
this.registerForm = fb.group({
email: ['', Validators.required, this._emailValidator.isAvailableEmail],
password: ['', Validators.compose([Validators.required, Validators.minLength(8)])],
phoneNumber: ['', Validators.required],
country: ['', Validators.required]
});
...
If someone could offer some guidance on what's occurring here, that'd be fantastic.
I reordered my code and produced the following:
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;
}
}
And amended its usage:
...
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]
});
...
Which works correctly.
Upvotes: 2