Reputation: 735
Component:
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { AF } from '../angularfire.service';
@Component({
selector: 'app-add-friend',
templateUrl: './add-friend.component.html',
styleUrls: ['./add-friend.component.less']
})
export class AddFriendComponent implements OnInit {
profileInfo = [];
currentUser = [];
requestToggle: boolean = false;
showButtons: boolean = true;
constructor(private afService: AF, private route: ActivatedRoute, private router: Router) {
let id = this.route.snapshot.params['id'];
// Get viewed profile details.
this.afService.getAthleteProfile(id).subscribe((data) => {
if (data.length > 0) {
let details = data[0];
this.profileInfo.push(details);
}
});
// Get current logged in user details.
afService.getCurrentUserInfo().then(currentUserDetails => {
this.currentUser.push(currentUserDetails);
});
}
// Send friend request.
addFriend() {
this.afService.addFriendRequest(this.profileInfo[0].userID, this.currentUser[0].userID, this.profileInfo[0].firstName, this.profileInfo[0].lastName, this.currentUser[0].firstName, this.currentUser[0].lastName).then(() => {
});
}
ngOnInit() {
// Check if friend request has been sent to display appropriate button.
setTimeout (() => {
if (this.currentUser) {
this.afService.getFriendRequests(this.profileInfo[0].userID, this.currentUser[0].userID).subscribe((data) => {
if (data.length > 0) {
this.requestToggle = true;
}
});
this.afService.getFriendRequestsFrom(this.profileInfo[0].userID, this.currentUser[0].userID)
.subscribe(data => {
if (data.length > 0) {
this.requestToggle = true;
}
});
}
// Hides buttons if on own profile.
if (this.profileInfo[0].userID == this.currentUser[0].userID) {
this.showButtons = false;
} else {
this.showButtons = true;
}
}, 1000);
}
}
Service:
import { Injectable } from "@angular/core";
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database';
import { Router, ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs/Rx';
import "rxjs/add/operator/map";
@Injectable()
export class AF {
public currentUserDetails;
constructor(public af: AngularFireAuth, private database: AngularFireDatabase, private router: Router) {
}
// Get all currently logged in user details.
getCurrentUserInfo() {
return new Promise((resolve, reject) => {
this.af.authState.subscribe(authData => {
let email = authData.email;
let array = this.database.list('registeredUsers', {
query: {
orderByChild: 'email',
equalTo: email
}
}).subscribe(data => {
let currentUserDetails = data[0];
resolve(currentUserDetails);
});
});
});
}
// Get all users details.
getAllAthletes(): Observable<any> {
return this.database.list('registeredUsers');
}
// Get useer details for the current profile route.
getAthleteProfile(userID) {
return this.database.list('registeredUsers', {
query: {
orderByKey: userID,
equalTo: userID
}
})
}
// Register new user.
registerUser(email, password) {
return this.af.auth.createUserWithEmailAndPassword(email, password);
}
// Add new user details to database.
addUserEntry(uid, fname, lname, email) {
return this.database.object('registeredUsers/' + uid).set({
firstName: fname,
lastName: lname,
email: email,
userID: uid,
bio: "Your short bio goes here...",
phone: 5555555555
});
}
// Add friend request to both parties.
addFriendRequest(profileUID, currentUID, profileFirstName, profileLastName, currentFirstName, currentLastName) {
return this.database.object('registeredUsers/' + currentUID + '/friends/requests/requestTo/' + profileUID).set({
requestTo: profileUID,
firstName: profileFirstName,
lastName: profileLastName
}).then(() =>
this.database.object('registeredUsers/' + profileUID + '/friends/requests/requestFrom/' + currentUID).set({
requestFrom: currentUID,
firstName: currentFirstName,
lastName: currentLastName
})
)}
/* (TODO): Consolidate lines 81-99. Replace the paths with variables set in the components.
---*
---*/
// Check if user sent a friend request to user being viewed.
getFriendRequests(profileUID, currentUID) {
return this.database.list('registeredUsers/' + currentUID + '/friends/requests/requestTo/' + profileUID)
}
// Check if user received a friend request from user being viewed.
getFriendRequestsFrom(profileUID, currentUID) {
return this.database.list('registeredUsers/' + currentUID + '/friends/requests/requestFrom/' + profileUID)
}
// Get all sent friend requests.
getPendingFriendRequests(currentUID) {
return this.database.list('registeredUsers/' + currentUID + '/friends/requests/requestTo/');
}
// Get all received friend requests.
getPendingFriendRequestsFrom(currentUID) {
return this.database.list('registeredUsers/' + currentUID + '/friends/requests/requestFrom/');
}
// Update the user account info.
updateUserEntry(uid, fname, lname, phone, bio) {
return this.database.object('registeredUsers/' + uid).update({
firstName: fname,
lastName: lname,
phone: phone,
bio: bio
});
}
// Login
loginWithEmail(email, password) {
return this.af.auth.signInWithEmailAndPassword(email, password).then(()=> {
this.router.navigate(['/dashboard']);
}).catch(function(error) {
var errorMessage = error.message;
})
}
// Logout
logout() {
this.af.auth.signOut().then(() =>
this.router.navigate(['/login'])
)}
}
Towards the end, I have the function wrapped in a 1 second setTimeout
function because the array currentUser
needs to be populated for it to run properly. The array always gets populated, but not fast enough, so the function never runs without the setTimeout
.
Instead of using a setTimeout
, is there any way to tell Angular to "Run this function after this array has been populated"?
Upvotes: 0
Views: 256
Reputation: 5730
First of all, no need for a Promise
in the service, you can simply return the observable:
import 'rxjs/add/operator/mergeMap';
getCurrentUserInfo() {
return this.af.authState.mergeMap(authData => {
return this.database.list('registeredUsers', {
query: {
orderByChild: 'email',
equalTo: authData.email
}
});
}).map(data => {
let currentUserDetails = data[0];
resolve(currentUserDetails);
});
}
Note: If you don't know how observables work, you should take a look at some tutorials.
After that, you can use this in your component. As we know, we need the currentUser
and the profileInfo
bevor we can execute your function. This means, that both observables need to be compleated:
import 'rxjs/add/observable/forkJoin';
Observable.forkJoin(
this.afService.getAthleteProfile(id),
this.afService.getCurrentUserInfo()
).subscribe((results) => {
results[0]; //This is the result of getAthleteProfile
results[1]; //This is the result of getCurrentUserInfo
//Now, push the values into the arrays
yourFunction(); //and execute your function here
});
Note: Don't forget to import your Observable operators:
import 'rxjs/add/observable/forkJoin';
import 'rxjs/add/operator/mergeMap';
Upvotes: 2