Issue
I created an app using Angular 7, and crud with firestore. Everything is working fine with one user. Now, I am trying to scale it, and associate data with each logged user. I can't find detailed material on the web.
I have users in collection. I want to create a collection of 'vacations' and nest it under each user, for his collection of vacations. I believe the first step, is to get the current logged user uid, and update whatever function I might have, to edit the collection, then .doc('current user id').
This is code I used to get current user's uid:
this.userID = this.firestore.collection('users').doc(this.auth().user.uid);
errors in pre-compiler:
1- Type 'AngularFirestoreDocument<{}>' is not assignable to type 'string'
2- Cannot invoke an expression whose type lacks a call signature. Type 'AuthService' has no compatible call signatures.
This is currently how the data is structured:
This is the auth service:
export class AuthService {
user$: Observable<User>;
constructor(
public afAuth: AngularFireAuth,
public afs: AngularFirestore,
public router: Router
) {
// Get the auth state, then fetch the Firestore user document or return null
this.user$ = this.afAuth.authState.pipe(
switchMap(user => {
// Logged in
if (user) {
return this.afs.doc<User>(`users/${user.uid}`).valueChanges();
} else {
// Logged out
return of(null);
}
})
)
}
googleLogin() {
const provider = new auth.GoogleAuthProvider()
return this.oAuthLogin(provider);
}
public oAuthLogin(provider) {
return this.afAuth.auth.signInWithPopup(provider)
.then((credential) => {
this.updateUserData(credential.user)
})
}
public updateUserData(user) {
// Sets user data to firestore on login
const userRef: AngularFirestoreDocument<User> = this.afs.doc(`users/${user.uid}`);
const data = {
uid: user.uid,
email: user.email,
displayName: user.displayName,
photoURL: user.photoURL
}
return userRef.set(data, { merge: true })
}
}
Appreciate your help.
Solution
Googles official answer can be found here - Get the currently signed-in user - Firebase
Below is a function that returns a promise of type string. The promise resolves with the user's uid which is returned from onAuthStateChangedwhich() along with the rest of the user's firebase auth object(displayName...etc).
getCurrentUser(): Promise<string> {
var promise = new Promise<string>((resolve, reject) => {
this.afAuth.auth.onAuthStateChanged(returnedUser => {
if (returnedUser) {
resolve(returnedUser.uid);
} else {
reject(null);
}
});
})
return promise
}
You would call it in the constructor or ngOninit:
userDoc: User = null;
constructor() {
this.getCurrentUser().then((userID: string) => {
//here you can use the id to get the users firestore doc
this.afs.collection('users').doc(userID).valueChanges()
.subscribe(userFirestoreDoc => { // remember to subscribe
this.userDoc = userFirestoreDoc;
})
}).catch(nullID => {
//when there is not a current user
this.userDoc = null
})
}
To add a collection for 'vacations' nested in the users doc you need to add a sub collection to the that users firestore doc. I would advise only doing this once the user gets/adds their first vacation. You can simply set a doc in the subcollection and if the sub collection doesn't already exist firestore will first create it and then add the new doc(vaction) so this is the only code you need to set the new collection and new vaction inside that collectio.
this.afs.collection('users').doc(this.userDoc.uid).collection('vacations).add(vactionObject).then(returnedVaction => {
}).catch(error => {
})
Answered By - Timothy Louw
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.