简体   繁体   English

Angular2 AngularFire2 providerData数组未在模板中更新

[英]Angular2 AngularFire2 providerData array not updating in Template

I have an Angular2 app that allows login via Google or Facebook using Firebase (via AngularFire2). 我有一个Angular2应用,该应用允许使用Firebase(通过AngularFire2)通过Google或Facebook登录。 It also permits linking of accounts, so that a user can link his/her Google and Facebook logins to the same Firebase uid. 它还允许链接帐户,以便用户可以将其Google和Facebook登录名链接到相同的Firebase uid。

On my ng2 User Profile component, for currently authenticated users, I want to be able to display a button for linking a FB or Google account if it is not already linked. 在我的ng2用户个人资料组件上,对于当前已通过身份验证的用户,我希望能够显示一个用于链接FB或Google帐户的按钮(如果尚未链接)。 AngularFire2 exposes an observable of type FirebaseAuthState that includes an “auth” property of type firebase.User. AngularFire2公开了FirebaseAuthState类型的可观察对象,其中包括firebase.User类型的“ auth”属性。 The firebase.User object includes a providerData array that includes all of the providers (Facebook, Google, Github, etc) associated with the user. firebase.User对象包含providerData数组,该数组包含与用户关联的所有提供程序(Facebook,Google,Github等)。 My AuthService looks something like this: 我的AuthService看起来像这样:

import * as firebase from 'firebase';
import { Injectable } from '@angular/core';
import { AuthProviders, AuthMethods, 
         FirebaseAuth, FirebaseAuthState } from 'angularfire2';

@Injectable()
export class AuthService {

  authState: FirebaseAuthState = null;

  constructor(private auth$: FirebaseAuth) {
    auth$.subscribe((state) => {this.authState = state;})
  }

  linkTo(provider:string): firebase.Promise<firebase.auth.UserCredential> {
    // provider param is a string (e.g., ‘facebook.com’);
    // linkWithPopup() returns a firebase promise of type firebase.AuthState 
    // Not included here: code to convert provider param from string to 
    // firebase.AuthProvider
    return this.authState.auth.linkWithPopup(provider);
  }

  unLinkFrom(provider:string): firebase.Promise<firebase.auth.UserCredential> {
    // provider is a string (e.g. ‘facebook.com’)
    // unlink() returns a firebase promise of type firebase.User.
    return this.authState.auth.unlink (provider);
  }

I can use this to determine which providers are already associate with a given user, and hide/show the requisite link buttons depending on whether a provider is contained within the user's providerData array. 我可以使用它来确定哪些提供程序已经与给定用户相关联,并根据提供程序是否包含在用户的providerData数组中来隐藏/显示必需的链接按钮。 In my component, for example: 在我的组件中,例如:

export class UserProfileComponent implements OnInit {

  private linkedProviders;

  constructor() {} (private authService: AuthService) {
    this. linkedProviders = authService.authState.auth.providerData;
  }
}

When I link a provider, firebase returns a firebase.Promise object. 当我链接提供程序时,firebase返回一个firebase.Promise对象。 On successful linking, I use .then() to update the local linkedProviders array, which contains the providerData array from Firebase. 成功链接后,我使用.then()更新本地链接的提供程序数组,该数组包含Firebase中的providerData数组。 For example: 例如:

  // Link a provider to the current account
  linkProvider(provider:string) {
    this.authService.linkTo(provider)
      .then((state) => this.linkedProviders = state.user.providerData)
      .catch(err => console.log(err));
  }

  // Unlink a provider from the current account
  unLinkProvider(provider:string) {
    this.authService.unLinkAccount(provider)
      .then(user => this.linkedProviders = user.providerData)
      .catch(err => console.log(err));
  }

However, the this.linkedProviders array doesn't seem to update automatically in the template using *ngFor when a user links or unlinks a provider, despite the fact that the .then() block of the linkProvider/unLinkProvider modifies it to reflect the updated data returned from the firebase Promise. 但是,尽管用户链接或取消链接了提供程序,但this.linkedProviders数组似乎并未使用* ngFor在模板中自动更新,尽管linkProvider / unLinkProvider的.then()块对其进行了修改以反映更新的事实。 Firebase Promise返回的数据。

Actually, it DOES seem to modify the local array data, as logging this.linkedProviders to the console will show. 实际上,它似乎确实在修改本地阵列数据,因为将this.linkedProviders记录到控制台将显示出来。 However, unless I click another button in the template, the change is not applied to the *ngFor. 但是,除非我单击模板中的另一个按钮,否则更改不会应用于* ngFor。 I can't figure why this is happening or how to work around it. 我不知道为什么会这样或如何解决。 I'm sure I'm missing something, but I can't figure out what. 我确定我缺少了一些东西,但是我不知道是什么。

It might be cleaner make authState an observable so the component can subscribe to it. authState设为可观察状态可能会更干净,因此组件可以对其进行订阅。 The component can then call linkWithPopup or unlink on the authState in the subscription. 然后,该组件可以在订阅中的authState上调用linkWithPopup或取消链接。 At the moment it looks like linkTo and unlinkFrom methods can be called before authState has been set. 目前看来,可以在设置authState之前调用linkTo和unlinkFrom方法。

        import * as firebase from 'firebase';
        import { Injectable } from '@angular/core';
        import {
            AuthProviders, AuthMethods,
            FirebaseAuth, FirebaseAuthState
        } from 'angularfire2';
        import { ReplaySubject } from 'rxjs/ReplaySubject';
        import { Observable } from 'rxjs/Observable';

        @Injectable()
        export class AuthService {
            private authStateSource = new ReplaySubject<FirebaseAuthState>(1);
            authState: Observable<FirebaseAuthState> = this.authStateSource.asObservable();

            constructor(private auth$: FirebaseAuth) {
                auth$.subscribe((state) => {
                    this.authStateSource.next(state);
                });
            }
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM