Reputation: 772
Hi I am building an angular application with @angular/fire. In the auth service I have a user observable which gets the value of the current user, if the user is authenticated, and the value of null if the user is not authenticated.
export class AuthService {
user$: Observable<User>;
constructor(private afAuth: AngularFireAuth, private afs:
AngularFirestore) {
this.user$ = this.afAuth.authState.pipe(
switchMap(user => {
if (user) {
return this.afs.doc<User>(`users/${user.uid}`).valueChanges();
} else {
return of(null);
}
})
)
}
It's in the service's constructor so all components that inject the service can see the user$ variable.Now lets say I have a navigation that shows different buttons based on if the user is authenticated or not.
<ul>
<!-- user IS NOT logged in -->
<li *ngIf="!(authService.user$ | async)">
This is visible if user is NOT logged in
</li>
<!-- user IS logged in -->
<li *ngIf="authService.user$ | async" fxHide.xs>
This is visible if user IS logged in
</li>
</ul>
The user$ observable is empty at the start and takes some time to take value which means even if the user is logged, in the template the "This is visible if user is NOT logged in" will be rendered for a couple of seconds before the observable takes the value of the current user and then switch to the other li tag. Is there any better way to check the authenticated user to prevent this? Note I cannot use route guard because i dont want to block a whole page but only some conditional logic between buttons and some other elements. This is a duplicate question to this one: Angular 6 AngularFireAuth check if user is logged in before page rendered where i did not find an answer. Thanks in advance
Upvotes: 1
Views: 491
Reputation: 4841
In the auth service add a subject to which the components can subscribe and wait for some response
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
@Injectable()
export class AuthService {
userAccessSubject = new Subject();
user$: Observable<User>;
constructor(private afAuth: AngularFireAuth, private afs:
AngularFirestore) {
this.afAuth.authState.pipe(
switchMap(user => {
if (user) {
this.userAccessSubject.next(this.afs.doc<User>(`users/${user.uid}`).valueChanges());
} else {
this.userAccessSubject.next(null);
}
})
)
}
getUserAccess() {
return this.userAccessSubject.asObservable();
}
}
And in the component, get userAccess from the subscription block
constructor() {
// Here add code to enable loader
this.authService.getUserAccess()
.subscribe(userAccessResponse => {
this.userAccess = userAccessResponse;
// Hide loader
})
}
Upvotes: 1