Я только начинаю изучать Angular 2 и Firebase и зациклился на основной проблеме.
Я использую метод Firebase createUserWithEmailAndPassword
для регистрации новой учетной записи пользователя с использованием данных формы HTML, которая хранится в пользовательском классе входа, а затем через метод.
Это работает, но я не могу понять, как передать любые данные об ошибках, которые я получаю в объекте ошибки, на мой шаблон HTML для отображения. Я добавил переменные в класс входа, но я не могу получить доступ к нему в методе createUserWithEmailAndPassword
.
Я знаю, что это, вероятно, что-то фундаментальное, но любая помощь будет действительно полезна. Благодарю!
LoginComponent.ts
import { Component } from "@angular/core";
import { Router } from "@angular/router";
import { Login } from "./login";
@Component({
selector: 'login-component',
templateUrl: 'app/login/login.component.html',
styleUrls:[
'app/login/login.component.css'
]
})
export class LoginComponent{
login = new Login('James', 'SuperSecret', false, '');
submitted = false;
onSubmit(){this.submitted= true};
active = true;
newUser(){
firebase.auth().createUserWithEmailAndPassword(this.login.email, this.login.pswd).catch(function(error) {
if(error){
console.log('The error code: ' + error.code + '\nThe error message' + error.message);
this.login.error = true;
this.login.errorMsg = error.message;
}else{
this.login.error=false;
this.login.errorMsg='';
}
});
}
}
LoginComponent.html
<div class="container">
<div [hidden]="submitted">
<h1>Login Form</h1>
<form *ngIf="active" (ngSubmit)="onSubmit()" #loginForm="ngForm">
<!-- Email Input -->
<div class="form-group">
<label for="email">Email</label>
<input type="email" class="form-control" id="email" required
[(ngModel)]="login.email" name="email" #email="ngModel">
<div [hidden]="email.valid || email.pristine"
class="alert alert-danger">
Email is required
</div>
</div>
<!-- Password Input -->
<div class="form-group">
<label for="pswd">Password</label>
<input type="password" class="form-control" id="pswd" [(ngModel)]="login.pswd" name="pswd" required>
<!-- EXAMPLE ERROR DISPLAY -->
<div [hidden]="!login.error" class="alert alert-danger">{{login.errorMsg}}</div>
</div>
<!-- Submit Buttons -->
<button type="submit" class="btn btn-default" [disabled]="!loginForm.form.valid">Login</button>
<button type="button" class="btn btn-default" (click)="newUser()">Register</button>
</form>
</div>
</div>
Login.ts (класс входа)
export class Login{
constructor(
public email: string,
public pswd: string,
public error: boolean,
public errorMsg: string
){}
}
Ваша проблема не связана с firebase или обещанием api, а с некоторой довольно общей ошибкой в том, как this
работает в javascript. Вы принимаете для доступа к LoginComponent
при назначении ошибки, но функция, переданная методу catch()
, не использует LoginComponent
как this
. Скорее всего, вы устанавливаете ошибку на объекте window
.
Существует несколько вариантов устранения этого.
Привязка к правилу:
newUser() {
firebase.auth()
.createUserWithEmailAndPassword(this.login.email, this.login.pswd)
.catch(
function(error) {
this.login.errorMsg = error.message;
}
.bind(this)
);
}
Используя закрытие:
newUser() {
// capturing 'this' in a variable
var self = this;
firebase.auth()
.createUserWithEmailAndPassword(this.login.email, this.login.pswd)
.catch(
function(error) {
// using the captured this (in the self variable)
self.login.errorMsg = error.message;
}
);
}
С помощью функций стрелок (которые не имеют this
аргумента и, следовательно, ищут this
во внешней области. Это требует ES2015, поэтому вам нужно перекрыть при таргетинге на старые браузеры. Поскольку вы используете TypeScript, я бы предложил использовать этот потому что это самый краткий.
newUser() {
firebase.auth()
.createUserWithEmailAndPassword(this.login.email, this.login.pswd)
.catch(
(error) => {
this.login.errorMsg = error.message;
// further assignments
}
);
}
Когда вам нужно выполнить одно действие, вы можете даже упростить это, опуская круглые скобки:
newUser() {
firebase.auth()
.createUserWithEmailAndPassword(this.login.email, this.login.pswd)
.catch(error => this.login.errorMsg = error.message);
}
Btw: При работе с API, основанным на обещаниях, вы должны быть в безопасности, не проверяя ошибку на наличие, когда вы реализуете обратный вызов catch
поскольку это вызывается только в случае ошибки...
Для получения дополнительной информации, пожалуйста, прочитайте этот отличный ответ об this
: Как получить доступ к правильному "этому" контексту внутри обратного вызова?