I'm currently trying to understand Angular 8 and created a little "Taskboard" Application. The goal is to have multiple tasks in different states assigned to different users.
I'm making multiple calls to an API with Observables. The first call is independent, but the following calls are dependent on the data gathered from the first call. (meaning I need to access /states/:stateid, where :stateid is stored in the object which I get from the first call.).
To make matters worse, it's an array of Objects, that I get from the first call.
Basically what I'm trying to do, is implementing a "join" in the angular app. Maybe this would be suited better in the backend, I'm not sure about that. Or maybe I completely miss the concept of NoSQL here.
The data is stored in a mongoDB:
States:
[
{"_id":"5dd1a81929672e116d3ac1dd","name":"Done"},
{"_id":"5dd1a81929672e116d3ac1de","name":"In Progress"},
{"_id":"5dd1a81929672e116d3ac1df","name":"To Do"}
]
Users:
[
{
"_id" : "5dd1a78ec241a19e508cd755",
"name": "test",
"email": "test@test.com",
"avatarurl": "https://www.w3schools.com/w3images/avatar2.png"
}
]
Tasks:
[
{
"watchers": [],
"_id": "5dd1a78ea9d379b57a8fd16b",
"title": "finish up rest endpoint",
"stateid": "5dd1a81929672e116d3ac1df",
"description": "blblblb"
},
{
"watchers": [],
"_id": "5dd1a78ea9d379b57a8fd16c",
"title": "create db",
"stateid": "5dd1a81929672e116d3ac1de",
"description": "create DB for website",
"assigne_id": "5dd1a78ec241a19e508cd755",
"reporter_id": "5dd1a78ec241a19e508cd755"
},
....
What I'm trying to accomplish, is to get all Tasks and their child-objects like assignee or state from their id.
This is my Task class in the angular app:
export class Task {
_id: string;
title: string;
state: State;
description: string;
assigne: User;
reporter: User;
watcher: User[];
}
And this are the methods I'm using, to get all the data from the backend:
public getAllTasks(): Observable<Task[]>{
return this.http.get(API_URL + '/tasks')
.map(r => {
const tasks = r.json();
return tasks.map((t) => this.mapTask(t));
})
.catch(this.handleError);
}
public mapTask(task: any) : Task {
let tsk = new Task(task);
if(task["assigne_id"]){
this.getUserForId(task["assigne_id"]).subscribe(
(assigne) => {
tsk.assigne = new User(assigne);
}
);
}
if(task["reporter_id"])
{
this.getUserForId(task["reporter_id"]).subscribe(
(reporter) => {
tsk.reporter = reporter;
}
);
}
if(task["stateid"])
{
this.getStateForId(task["stateid"]).subscribe(
(state) => {
tsk.state = state;
}
);
}
tsk.watcher = []
for (let index = 0; index < task["watchers"].lenght; index++) {
const watcher = task["watchers"][index];
if(watcher)
{
this.getUserForId(watcher).subscribe(
(w) => {
tsk.watcher.push(w);
}
);
}
}
return tsk;
}
The methods for getting the users, states etc.. are all similar to this one:
public getUserForId(id:string) : Observable<User> {
return this.http.get(API_URL + '/users/' + id)
.map(r => {
return new User(r.json());
})
.catch(this.handleError);
}
So I have a couple of questions:
- Am I supposed to store the user as an object into the task object on my MongoDB? Wouldn't I lose consistency, say for when a user changes his email, this way?
- Is there an easy way to handle this "join" with switchMap, forkJoin or something like that (since they're all observables)?
Ideally, I would make a request to the /tasks endpoint to get all the tasks objects from the DB and then make multiple requests in parallel to the endpoints for the single user or state by ID for each Task.
I read that forkJoin makes this possible, but it seems, that forkJoin is deprecated... Are there any alternatives or ways to solve this problems?
Thanks in advance
cheers