Как передать значения из метода Firebase 3 с Angular 2

0

Я только начинаю изучать 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
    ){}
}
  • 0
    Я могу взаимодействовать с объектом входа, если я добавляю метод .then () после .catch (). Почему я не могу получить к нему доступ в анонимной функции .catch?
Теги:
angular
firebase
firebase-authentication
firebase-realtime-database

1 ответ

1
Лучший ответ

Ваша проблема не связана с 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: Как получить доступ к правильному "этому" контексту внутри обратного вызова?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню