简体   繁体   English

Angular 8 菜单中的用户登录/注销按钮未更新

[英]User login/logout button in menu Angular 8 not updating

I have a mat-toolbar with a login/logout button where the user of the website can login or out at all times.我有一个带有登录/注销按钮的mat-toolbar ,网站用户可以随时登录或退出。 I have an authentication service which creates an Observable with user data and using *ngIf="!(authService.user$ | async) for the login button. This isn't working though, unless I manually refresh the whole page. Why is this and what does one do about it? I thought the Observable would be a way that would actually work in these situations, but obviously I am missing something.我有一个身份验证服务,它使用用户数据创建一个 Observable 并使用*ngIf="!(authService.user$ | async)作为登录按钮。但这不起作用,除非我手动刷新整个页面。这是为什么以及如何处理它?我认为 Observable 将是一种在这些情况下实际可行的方式,但显然我遗漏了一些东西。

I have also tried subscribing to the Observable as user in app.component.ts and using user in the template, but this doesn't seem to help.我也曾尝试订阅的观察为userapp.component.ts和使用user的模板,但是这似乎并没有帮助呢。 I know there are several questions regarding user login with Observables, and questions about refresh, but they haven't given me an understanding of why this isn't working.我知道有几个关于用户使用 Observables 登录的问题,以及关于刷新的问题,但他们并没有让我理解为什么这不起作用。

I should perhaps add that I am using an interface User with property roles , for role based authorisation, so it is not the same as firebase.User .我或许应该补充一点,我正在使用一个接口User和属性roles ,用于基于角色的授权,所以它与firebase.User

Relevant parts of authentication.service.ts : authentication.service.ts 的相关部分:

@Injectable({
  providedIn: 'root'
})

export class AuthenticationService {
  user$: Observable<User>;
  viewAllUser: Boolean = false;

  constructor(
    private afAuth: AngularFireAuth,
    private afs: AngularFirestore,
    private router: Router) {

    this.user$ = this.afAuth.authState.pipe(
      switchMap(user => {
        if (user) {
          return this.afs.doc<User>(`Users/${user.uid}`).valueChanges()
        } else {
          return of(null)
        }
      }))
  }

  /* Sign up */
  SignUp(email: string, password: string) {
    this.afAuth.auth.createUserWithEmailAndPassword(email, password)
      .then((result) => {
        window.alert("You have been successfully registered!");
        this.updateUserData(result.user)
        //console.log(result.user);
      }).catch((error) => {
        window.alert(error.message);
        //console.log(error.user);
      });
  }

  /* Sign in */
  SignIn(email: string, password: string) {
    return this.afAuth.auth.signInWithEmailAndPassword(email, password)
      .then((result) => {
        window.alert("You have been successfully signed in!");
        this.updateUserData(result.user);
        //console.log(result.user);
      }).catch((error) => {
        window.alert(error.message);
        //console.log(error.user);
      });
  }

  /* Sign out */
  SignOut() {
    this.router.navigate(['user-main']);
    this.afAuth.auth.signOut();
    window.alert("You have been successfully signed out!");
  }

 private updateUserData(user) {
        // Sets user data to firestore on login
        const userRef: AngularFirestoreDocument<any> = this.afs.doc(`Users/${user.uid}`);
        const data: User = {
          uid: user.uid,
          email: user.email,
          roles: {
            role1: true //default role
          }
        }
        return userRef.set(data, { merge: true }) //Update in non-destructive way 
      }
}

app.component.html: app.component.html:

<body>
  <mat-toolbar>
    <span>
      <button mat-menu-item *ngIf="!(authService.user$ | async) as user" routerLink="/user-main">Login</button>
      <button mat-menu-item (click)="authService.SignOut()" routerLink="/user-main" *ngIf="authService.user$ | async">Logout</button>
      {{user.email}} //for testing
    </span>
    <span>
      <button mat-icon-button [matMenuTriggerFor]="appMenu">
        <mat-icon>more_vert</mat-icon>
      </button>
    </span> 
  </mat-toolbar>
  <mat-menu #appMenu="matMenu">
    <!-- Only to be shown to logged in users: -->
    <button mat-menu-item *ngIf="authService.user$ | async" routerLink="/user-main">User main</button>
    <button mat-menu-item *ngIf="authService.user$ | async" routerLink="/page_x">Page X</button>
    <button mat-menu-item *ngIf="authService.canViewData(authService.user$ | async)==true" routerLink="/secret_page_y">Secret page Y</button>
  </mat-menu>

  <!--This is where the routes are shown-->
  <router-outlet></router-outlet>
</body>

app.component.ts: app.component.ts:

import { Component } from '@angular/core';
import { AuthenticationService } from './shared/authentication.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  user;

  constructor(public authService: AuthenticationService) {
    this.authService.user$.subscribe(user => this.user = user);
  }
}

You should use a BehaviorSubject for the user and use it like :您应该为用户使用BehaviorSubject并像这样使用它:

authentication.service.ts:身份验证.service.ts:

    private currentUserSubject = new BehaviorSubject<User>({} as User);
    public currentUser = this.currentUserSubject.asObservable().pipe(distinctUntilChanged());

  getCurrentUser(): User {
    return this.currentUserSubject.value;
  }
      /* Sign up */
      SignUp(email: string, password: string) {
        this.afAuth.auth.createUserWithEmailAndPassword(email, password)
          .then((result) => {
            window.alert("You have been successfully registered!");
            this.updateUserData(result.user);
            //console.log(result.user);
          }).catch((error) => {
            window.alert(error.message);
            //console.log(error.user);
          });
      }

      /* Sign in */
      SignIn(email: string, password: string) {
        return this.afAuth.auth.signInWithEmailAndPassword(email, password)
          .then((result) => {
            window.alert("You have been successfully signed in!");
            this.updateUserData(result.user);
            //console.log(result.user);
          }).catch((error) => {
            window.alert(error.message);
            //console.log(error.user);
          });
      }


      private updateUserData(user) {
        // Sets user data to firestore on login
        const userRef: AngularFirestoreDocument<any> = this.afs.doc(`Users/${user.uid}`);
        const data: User = {
          uid: user.uid,
          email: user.email,
          roles: {
            role1: true //default role
          }
        }
        this.currentUserSubject.next(data); // --> here
        return userRef.set(data, { merge: true }) //Update in non-destructive way 
      }
}

app.component.ts: app.component.ts:

this.authService.currentUser.subscribe(user => this.user = user);

auth-guard.service.ts: auth-guard.service.ts:

const user = this.authService.getCurrentUser();
if (user.id) {
   return true;
} else {
   return false;
}

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

相关问题 Angular(5)-成功登录后,登录按钮未更改为注销 - Angular(5) - Login button not changing to Logout on successful login 仅在Angular 7中登录后启用注销按钮 - enable Logout button only after Login in Angular 7 注销用户并重定向用户以在令牌到期时登录 - Angular 8 - Logout User and Redirect User to Login on Token Expiration - Angular 8 Angular 中的登录/注销导航 - login/logout navigation in Angular 如果用户处于注销状态,Angular2,重定向到登录页面 - Redirect to login page if user is in logout state, Angular2 用户在Ionic 4中登录后无法立即显示注销按钮 - Not able to show the logout button immediately after the user login in Ionic 4 在同一页面上使用 angular 登录和注销 - login and logout with angular on the same page 首次登录失败,刷新页面强制用户在Angular+(Node/express).js中注销 - Login fails for the first time login and refreshing page forces user to logout in Angular+(Node/express).js Angular BehaviorSubject订阅。 用户登录和注销后组件中的调用方法 - Angular BehaviorSubject Subscribe. Call method in component after user login and logout Angular + Firebase在注销时删除用户 - Angular + Firebase Delete user on logout
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM