【问题标题】:Re-rendering the FirebaseUI Auth widget in Angular 8 single page application not working在 Angular 8 单页应用程序中重新渲染 FirebaseUI Auth 小部件不起作用
【发布时间】:2020-05-22 18:35:00
【问题描述】:

我创建了一个新的 Angular 8 CLI 项目,该项目与 FirebaseUI Auth 集成,使用电子邮件和密码登录。 FirebaseUI Auth 小部件在用户注销后不会显示。这是一个错误还是我在文档中遗漏了什么?

该应用是单页应用。

我已经根据 app.module.ts 中的文档注册了 Firebase:

// Firebase App (the core Firebase SDK) is always required and must be listed first
import * as firebase from "firebase/app";

// If you enabled Analytics in your project, add the Firebase SDK for Analytics
import "firebase/analytics";

// Add the Firebase products that you want to use
import "firebase/auth";
import "firebase/firestore";

// Initialize Firebase
firebase.initializeApp(environment.firebaseConfig);

frontpage.component.html 中,我根据文档实现了 FirebaseUI 小部件:

<h1>Welcome - User is logged out!</h1>
<div id="firebaseui-auth-container"></div>
<div id="loader">Loading...</div>

frontpage.component.ts 我有:

import { Component, OnInit } from '@angular/core';
import * as firebase from 'firebase/app';
import * as firebaseui from 'firebaseui';
import { Router } from '@angular/router';

@Component({
  selector: 'app-frontpage',
  templateUrl: './frontpage.component.html',
  styleUrls: ['./frontpage.component.less']
})
export class FrontpageComponent implements OnInit {

  ui: firebaseui.auth.AuthUI

  constructor(private router: Router) { 

  }

  ngOnInit() {

    if(firebaseui.auth.AuthUI.getInstance("[DEFAULT]") === null){
      // Initialize the FirebaseUI Widget using Firebase.
      this.ui = new firebaseui.auth.AuthUI(firebase.auth());
    }else{
      this.ui = firebaseui.auth.AuthUI.getInstance("[DEFAULT]");
    }

    var firebaseUIConfig = {
      callbacks: {
        signInSuccessWithAuthResult: function (authResult, redirectUrl) {
          // User successfully signed in.
          // Return type determines whether we continue the redirect automatically
          // or whether we leave that to developer to handle.

          //Manual override to let firebase.auth().onAuthStateChanged handle routing (instead of signInSuccessUrl shown below)
          return false;

          //return true;
        },
        uiShown: function () {
          // The widget is rendered.
          // Hide the loader.
          document.getElementById('loader').style.display = 'none';
        }
      },
      // Will use popup for IDP Providers sign-in flow instead of the default, redirect.
      signInFlow: 'popup',
      signInSuccessUrl: '<url-to-redirect-to-on-success>',
      signInOptions: [
        // Leave the lines as is for the providers you want to offer your users.
        //firebase.auth.GoogleAuthProvider.PROVIDER_ID,
        //firebase.auth.FacebookAuthProvider.PROVIDER_ID,
        //firebase.auth.TwitterAuthProvider.PROVIDER_ID,
        //firebase.auth.GithubAuthProvider.PROVIDER_ID,
        //firebase.auth.EmailAuthProvider.PROVIDER_ID,
        {
          provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
          requireDisplayName: false
        }
        //firebase.auth.PhoneAuthProvider.PROVIDER_ID
      ],
      // Terms of service url.
      tosUrl: '<your-tos-url>',
      // Privacy policy url.
      privacyPolicyUrl: '<your-privacy-policy-url>'
    };

    this.ui.reset(); // according to https://github.com/firebase/firebaseui-web#tips-for-initializing-a-new-ui-instance-with-the-same-auth-instance

    // The start method will wait until the DOM is loaded.
    this.ui.start('#firebaseui-container', firebaseUIConfig);
  }

  ngOnDestroy() {

    // according to https://github.com/firebase/firebaseui-web#050
    this.ui.reset(); // according to https://github.com/firebase/firebaseui-web#tips-for-initializing-a-new-ui-instance-with-the-same-auth-instance
    this.ui.delete();
  }  

}

user-profile.component.html

<h1>Welcome - User is logged in!</h1>
<button mat-raised-button color="primary" (click)="signOut()">Sign out</button>

user-profile.component.ts

import { Component, OnInit } from '@angular/core';
import * as firebase from 'firebase/app';

@Component({
  selector: 'app-user-profile',
  templateUrl: './user-profile.component.html',
  styleUrls: ['./user-profile.component.less']
})
export class UserProfileComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

  signOut(){
    firebase.auth().signOut();
  }
}

authentication.service.ts 被注入到 app.component.ts 中,其中 firebase.auth().onAuthStateChanged 在更改时被调用在 Auth 对象中 - 产生 i 路由:

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import * as firebase from 'firebase/app';


@Injectable({
  providedIn: 'root'
})
export class AuthenticationService {

  isLoggedIn = false;

  constructor(private router: Router) {

    firebase.auth().onAuthStateChanged(user => {
      if (user) {
        // User is signed in.

        this.isLoggedIn = true;
        this.router.navigate(['/profile']);
      } else {
        // No user is signed in.

        this.isLoggedIn = false;
        this.router.navigate(['/frontpage']);
      }
    });

  }
}

【问题讨论】:

    标签: angular firebase firebase-authentication single-page-application firebaseui


    【解决方案1】:

    您应该考虑使用AngularFire。将Firebase 集成到您的 Angular 应用中是最佳选择。

    FirebaseUI-web 是可选的,您可以将它与 AngularFire 一起使用,例如用于 UI 登录按钮。

    安装和使用 AngularFire

    yarn add @angular/fire.

    在您的应用程序模块中导入AngularFireModuleAngularFireAuthModule

    const config = {
      apiKey: "YOUR API KEY",
      authDomain: "PROJECT_ID.firebaseapp.com",
    };
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        AngularFireModule.initializeApp(config),
        AngularFireAuthModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    

    然后,在组件中使用它(来自官方文档的代码 sn-p):

    import { Component } from '@angular/core';
    import { AngularFireAuth } from '@angular/fire/auth';
    import { auth } from 'firebase/app';
    
    @Component({
      selector: 'app-root',
      template: `
        <div *ngIf="auth.user | async as user; else showLogin">
          <h1>Hello {{ user.displayName }}!</h1>
          <button (click)="logout()">Logout</button>
        </div>
        <ng-template #showLogin>
          <p>Please login.</p>
          <button (click)="login()">Login with Google</button>
        </ng-template>
      `,
    })
    export class AppComponent {
      constructor(public auth: AngularFireAuth) {
      }
      login() {
        this.auth.signInWithPopup(new auth.GoogleAuthProvider());
      }
      logout() {
        this.auth.signOut();
      }
    }
    

    FirebaseUI-Web 作为一个选项

    您也可以使用 FirebaseUI-Web 来集成不同提供商的“登录”按钮,例如,它可以与 AngularFire 配合使用。

    为此,请查看:

    【讨论】:

    • 嗨@Thierry Falvo,感谢您的快速回复。我不明白 FirebaseUI-Web 和 AngularFire 之间的区别,或者更具体地说,AngularFire 会给我什么是 FirebaseUI-Web 无法做到的——除了 2 个额外的依赖项。 FirebaseUI-Web 的唯一问题是它无法显示登录小部件,除非重新加载页面。因此,我可以将 signInSuccessWithAuthResult 设置为返回 TRUE 并提供一个 signInSuccessUrl。这将在成功登录时刷新页面。但它会重新加载页面......并不是真正的 SPA 体验。使用 FirebaseUI-Web 真的不可能吗?
    • 首先,让你的应用只使用 firebase 和 @angular/fire。然后,您可以尝试将 FirebaseUI 用于内置登录按钮等。但这是两件不同的事情。但 FirebaseUI 不是强制性的。另一方面,@angular/fire 是将 Firebase 集成到 Angular 应用程序的最佳选择。我更新了我的答案。
    【解决方案2】:

    使用 firebase 控制台中的 firebase 配置文件首先在您的应用程序中初始化 firebase

    import { firebaseConfig } from '../../../environments/environment';
    
    
        firebase.initializeApp(firebaseConfig)
        this.ui = new firebaseui.auth.AuthUI(firebase.auth());
    

    【讨论】:

      猜你喜欢
      • 2016-12-07
      • 1970-01-01
      • 2016-02-16
      • 1970-01-01
      • 1970-01-01
      • 2021-10-27
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多