Reputation: 435
I'm setting up a customized user database in firebase where the document id will be stored using the user authentication uid.
The issue I'm currently facing now is storage the current user document to display on my dashboard when the user logs in.
Currently, on my authService.ts I'm storing the data from firebase.user
which on my dashboard will display only information from the default array.
This is what I have in my auth.service.ts
export class AuthService {
userData: any;
userCollection: AngularFirestoreCollection<User>;
constructor(
public afs: AngularFirestore, // Inject Firestore service
public afAuth: AngularFireAuth, // Inject Firebase auth service
public router: Router,
public ngZone: NgZone, // NgZone service to remove outside scope warning
) {
/* Saving user data in localstorage when
logged in and setting up null when logged out */
this.afAuth.authState.subscribe(user => {
if (user) {
this.userData = user;
localStorage.setItem('user', JSON.stringify(this.userData));
JSON.parse(localStorage.getItem('user'));
this.UserID = this.userData.uid;
} else {
localStorage.setItem('user', null);
JSON.parse(localStorage.getItem('user'));
}
})
}
SignUp(username, email, password) {
return this.afAuth.auth.createUserWithEmailAndPassword(email, password)
.then((result) => {
// set account doc
let created_data = JSON.parse(JSON.stringify(result.user));
const account = {
uid: result.user.uid,
created_time: created_data.createdAt,
email: result.user.email,
display_name: username,
photoURL: result.user.photoURL,
}
this.SetUserData(account);
}).catch((error) => {
window.alert(error.message)
})
}
/* Setting up user data when sign in with username/password,
sign up with username/password and sign in with social auth
provider in Firestore database using AngularFirestore + AngularFirestoreDocument service */
SetUserData(user) {
const userRef: AngularFirestoreDocument<User> = this.afs.doc(`users/${user.uid}`);
const userData: User = {
bio: null,
country: {
country: null,
country_code:null,
symbol:null
},
gender: "unspecified",
languages: null,
profile_pic: user.photoURL,
username: user.display_name,
}
return userRef.set(userData, {
merge: true
})
}
}
and on my dashboard.component.ts
export class DashboardComponent implements OnInit {
isLoggedIn$: Observable<boolean>;
isLoggedOut$:Observable<boolean>;
constructor(
public afAuth: AngularFireAuth,
public authService: AuthService
) { }
ngOnInit() {
this.isLoggedIn$ = this.afAuth.authState.pipe(map(user => !!user));
this.isLoggedOut$ = this.isLoggedIn$.pipe(map(loggedIn => !loggedIn));
}
}
with this, I can only get details from whatever is stored in firebase.user and not my customized DB. How do I get into the specific document based on the authenticated user's UID so that I can display the information like bio, gender, and languages?
this is how I'm parsing in the information on my dashboard.html
<!-- Main content -->
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-4">
<div class="inner-adjust">
<div class="pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">User Profile</h1>
</div>
<!-- Show user data when logged in -->
<div class="row" *ngIf="authService.userData as user">
<div class="col-md-12">
<div class="media">
<img class="align-self-start mr-5 img-thumbnail rounded-circle" src="{{(user.photoURL) ? user.photoURL : '/assets/placeholder-user.jpg'}}"
alt="{{user.displayName}}">
<div class="media-body">
<h1>Hello: <strong>{{(user.username)}}</strong></h1>
<p>Email: <strong>{{user.email}}</strong></p>
<p>Gender: <strong>{{user.gender}}</strong></p>
<p>Languages: <strong>{{user.languages}}</strong></p>
</div>
</div>
</div>
<!-- </div> -->
</div>
</div>
</main>
Upvotes: 2
Views: 2123
Reputation: 73357
I don't see the need to use localStorage
, firebase will emit the authstate as long as app is running and if user does not happen to be logged in, authState
returns null
.
By the way - Also you are using JSON.parse(JSON.stringify(...))
in one place, which makes little sense ;)
Anyway, I have a similar setup and this is how I do it:
in the auth service:
user$ = this.afAuth.authState.pipe(
switchMap(user => {
if (user) {
return this.afs.doc<any>(`users/${user.uid}`).valueChanges();
} else {
return of(null);
}
})
);
Then I just subscribe to the user$
where I need it. Either do that by manually subscribing or using async
pipe. If you want to manually subscribe you need to remember to unsubscribe also on component destroy.
Here sample using async pipe:
user$ = this.authService.user$;
constructor(private authService: AuthService) { }
Template:
<div *ngIf="(user$ | async) as user">
<h1>Hello: <strong>{{ user.username }}</strong></h1>
</div>
Also, DON'T use any
. Please create models (interface is my preference) for your data. We are working with TypeScript after all ;)
Upvotes: 5