简体   繁体   中英

Firestore Angular Collection inside Document

I have a collection of documents for every instructor and I want to have another collection of comments for each doc. I can't find a way to read that sub collection. Here is the structure:

结构 pt1

结构 pt2

I take the specific id from a service here:

getInstructor(iid: string) {
    this.instructorDoc = this.afs.doc<Instructors>(`instructors/${iid}`);
    return this.instructorDoc.valueChanges();  
}

I call the function on the instructor page:

getInstructor(): void {
    const iid = this.route.snapshot.paramMap.get('iid');
    this.instructorsService.getInstructor(iid).subscribe(instructor => this.instructor = instructor);   
}

I also have an interface for instructors:

export interface Instructors {
  iid: string;
  first_name: string;
  last_name: string;
  category: string;
  location: string;
  description: string;
  photoURL: string;
}

Finally I have the html of the instructor component like this:

<div *ngIf="instructor" class="card" style="width: 18rem;">
  <img [src]="instructor.photoURL || '//:0'" alt="" class="card-img-top">
  <div class="card-body">
    <h5 class="card-title">{{ instructor.iid }} {{ instructor.first_name }} {{ instructor.last_name }}</h5>
    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's
      content.</p>
  </div>
</div>

All the code works. I'm just stuck and can't figure how to go from here. Should I declare the comments somehow in the instructor interface? Also should somehow take the id of the comment (maybe add cid field in the comment doc). And how I will show the comment content in the html. I'm new to JavaScript/TypeScript/Angular and maybe these things are easy but I wasn't able to find helpful info on google on the specific situation.

You should be able to do the following in order to retrieve a Comment document:

getComment(iid: string, commentId: string) {
    this.commentDoc = this.afs.doc<Comment>(
        `instructors/${iid}/comments/${commentId}`
    );
    return this.commentDoc.valueChanges();  
}

With this interface or similar:

export interface Comment {
    id?: string;
    content: string;
}

About getting the comment ID, I think it really depends on what you are doing. For example if you were to have a post with multiple comments of multiple people, if a comment can be interacted with it would be a good idea to leave the comment ID inside an HTML tag so it can be retrieved to perform a query with it. In another scenario you may want to iterate on all the comments, which would be different.

That last aspect of your question may need more clarification and it's probably worth of another question going into more detail about your application.


After discussing the problem in the comments I found that there's a lack of understanding about the application's workflow. I will try to explain what is missing and I will show how to fix it.

Misconception

The designed web has the routes defined in src/app/app-routing.module.ts . There are these routes defined:

{
    path: '',
    redirectTo: '/instructors',
    pathMatch: 'full'
},
{
    path: 'instructors',
    component: InstructorsComponent
},
{
    path: 'instructors/:iid',
    component: InstructorDetailsComponent,
}

We can understand from there that /instructors will act as the index page and /instructors/:iid will be the detail of each instructor.

When a user goes to your main page and clicks on the profile of an instructor, notice how you are accessing /instructors/:iid . Thus, you are only forwarding the id of the instructor ( iid ). This is correct because we don't have the need to forward this on the URL, we are only inspecting the instructor.

const cid = this.route.snapshot.paramMap.get('cid');

Therefore the line above in the file instructor-details.component.ts doesn't make sense because it retrieves the parameter cid which it's not being forwarded on the URL for the instructor's details.

Actually if that line is changed to const cid = "a8OA7dCBNuNE8uTwgvhk" you will see that the whole function works and it's displayed properly on the page of the first instructor ( 5EdG4liyxxjam9BrCt0T ).

Fix

As I understand, you want to show all the comments of an instructor on their details page. This means that the application has to retrieve the subcollection comments of the appropriate instructor and display them.

In order to solve this I have modified three files:

instructor-details.component.ts

First the retrieval of the parameter cid has to be removed, as it will never be there. The following setup tells us that the function InstructorsService.getComments will retrieve all the comments of the instructor iid and return them in order to display them.

getComments(): void {
    const iid = this.route.snapshot.paramMap.get('iid');
    this.instructorsService.getComments(iid).subscribe(comments => {
        this.comments = comments;
    });
}

instructors.service.ts

Now this function has to retrieve the whole collection of comments instead of a single one having the id. Notice that the commentDoc has now changed to commentCol and has changed its type, as the query is now retrieving a whole collection instead of a single document.

import {AngularFirestore, AngularFirestoreDocument, AngularFirestoreCollection} from '@angular/fire/firestore';

[..]

export class InstructorsService {
    instructorDoc: AngularFirestoreDocument<Instructors>;
    commentCol: AngularFirestoreCollection<Comments>;

    [..]

    getComments(iid: string) {
        this.commentCol = this.afs.collection<Comments>(`instructors/${iid}/comments`);
        return this.commentCol.valueChanges();
    }

}

instructor-details.component.html

In the HTML component, instead of displaying the value, it has been changed to the iterator ngFor , since the component is now receiving a list of documents.

<div *ngFor="let comment of comments"> {{comment.content}} </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM