angular - Angular 8 菜单中的用户登录/注销按钮未更新
问题描述
我有mat-toolbar
一个登录/注销按钮,网站用户可以随时登录或注销。我有一个身份验证服务,它使用用户数据创建一个 Observable 并*ngIf="!(authService.user$ | async)
用于登录按钮。但这不起作用,除非我手动刷新整个页面。为什么会这样,人们会怎么做?我认为 Observable 将是一种在这些情况下实际工作的方式,但显然我错过了一些东西。
我也尝试过user
在app.component.ts中订阅 Observable并在模板中使用user
,但这似乎没有帮助。我知道有几个关于用户使用 Observables 登录的问题,以及关于刷新的问题,但他们没有让我理解为什么这不起作用。
我也许应该补充一点,我正在使用User
带有属性的接口roles
,用于基于角色的授权,因此它与firebase.User
.
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:
<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:
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);
}
}
解决方案
您应该BehaviorSubject
为用户使用 a 并像这样使用它:
身份验证.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:
this.authService.currentUser.subscribe(user => this.user = user);
auth-guard.service.ts:
const user = this.authService.getCurrentUser();
if (user.id) {
return true;
} else {
return false;
}
推荐阅读
- python - 元组对象不是可调用问题。(简单鳕鱼)
- python - Scrapy在身份验证后抓取每个链接
- mysql - 如何针对数组在表中搜索json编码的数组列并返回匹配结果?
- java - 基于字符偏移的动态重新定位的字符阅读器(如 FileReader)
- javascript - JavaScript 日期元素显示为第二天而不是当天
- excel - 将数据从 excel 复制到现有的 powerpoint 图表
- javascript - 使用 .select jquery 但没有得到任何选定的文本
- javascript - HTML5 直接从 Safari iOS 上的照片库中选择照片
- python - Python中的df_dict
- kivy - 在 RecyleView kivy 中添加 KivyMD 扩展面板