【问题标题】:How to pass values out of Firebase 3 method with Angular 2如何使用 Angular 2 从 Firebase 3 方法中传递值
【发布时间】:2016-09-05 23:45:33
【问题描述】:

我刚刚开始学习 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
    ){}
}

【问题讨论】:

  • 如果我在 .catch() 之后添加一个 .then() 方法,我就能够与登录对象交互。为什么我不能在 .catch 匿名函数中访问它?

标签: angular typescript firebase firebase-realtime-database firebase-authentication


【解决方案1】:

您的问题与 firebase 或 promise api 无关,而是关于 this 如何在 javascript 中工作的一些非常普遍的错误。您假设在分配错误时访问LoginComponent,但传递给catch() 方法的函数不使用LoginComponent 作为this。您很可能在 window 对象上设置了错误。

有几个选项可以解决这个问题。

绑定正确的this:

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);
}

顺便说一句:在使用基于承诺的 API 时,您应该在实现 catch 回调时不检查错误是否存在是安全的,因为只有在发生错误时才会调用它...

有关更多详细信息,请阅读有关this的出色答案:How to access the correct `this` context inside a callback?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    相关资源
    最近更新 更多