0
votes

I'm using @angular/fire to fetch data from firestore. I have two components. one is parent and the other is child. Both of these components are subscribing to observable using async pipes. These are two different observables (but on the same collection). When i arrive on the child route i can see the data from parent route is there until the child component's observable gives response and replaces the data that shouldn't be there. Why is this happening?

This is the method that returns an observable which is used the parent component.

getMyTasks(workspaceID, userID) {
return this.afs.collection('Tasks', ref => ref.where(`workspaceID`, '==', workspaceID).where(`members.${userID}`, '==', true))
  .snapshotChanges().pipe(
    map(actions => actions.map(a => {
      const data = a.payload.doc.data() as Task;
      const id = a.payload.doc.id;
      let member = data.members;
      let isMember = false;
      for (var b in Object.keys(data.members)) {
        if (Object.keys(member)[b] === userID) {
          isMember = true;
          break;
        } else {
          isMember = false;
        }
      }

      let createdBy = data.createdBy;
      let creatorName = "";

      for (let i = 0; i < this.members.length; i++) {
        if (this.members[i].memberId === createdBy) {
          creatorName = this.members[i].data.name;
        }
      }
      return { id, creatorName, isMember, ...data };
    }))
  );

}

this.tasks$ = this.firestoreService.getMyTasks(this.workspaceID, this.userID);

And then i'm using async pipe in the template. And here is the method which is used in child component

getTasks(projectId, members) {
return this.afs.collection('Tasks', ref => ref.where('projectId', '==', projectId).orderBy("createdAt", "desc"))
  .snapshotChanges().pipe(map(actions => actions.map(a => {
    const data = a.payload.doc.data() as Task;
    const docId = a.payload.doc.id;
    let createdBy = data.createdBy;
    let creatorName = "";

    for (let i = 0; i < members.length; i++) {
      if (members[i].memberId === createdBy) {
        creatorName = members[i].data.name;
      }
    }

    return { docId, ...data, creatorName }
  })))}

this is child component.ts

this.tasks = this.firestoreService.getTasks(this.projectId, this.members);
1

1 Answers

0
votes

It seems the CollectionReference is an object which exists only once per collection.

So if you do another query to this collection the first query is overwritten but the subscription stays active.

The parent and the child listen both for the same query hence the duplicate results.

I see three solutions to solve this problem.

  1. The parent should just get the data once and the child could listen to data changes.

  2. If the child is showing Tasks which are belonging to the parent Task. You should create a collection for these Sub-Tasks and query this collection.

  3. If you do not need the data updated on changes you could just get all the data once.

I depends on what you are trying to achieve.

Edit:

If all document have the same structure.

  1. You could query all the documents you need. Maybe all documents which the user can access.

    Then you could create a service which subscribes to the query observable. Now you have to process the documents, filter or whatever. And create two new observable which emit your filtered documents.

    Every time the query observable emits an update, you could emit the newly updated data with your observables.

This way you just can use async pipe on your observables.

This is maybe the best solution if there is a connection between your parent and child Tasks.