Angular Firestore - 显示子文档数组的内容

Angular Firestore - Display contents of sub-document array

这道题的设置很长。最后,我要求语法指导,如果你滚动到设置的末尾,你会看到这个问题。

我有一个 Firestore 数据库,它有一个包含数组的字段。这是一个例子:

文档本身还有 ingredients 元素之外的其他字段。这是您在此处看到的 Congo Split 食谱的 JSON 表示:

"congosplit": {
  "ingredients": {
    "a": {
      "ingredientAmounts": "2 Pump, 3 Pumps, 4 Pumps",
      "ingredientName": "Banana Syrup",
      "ingredientSizes": "Small, Medium, Large"
    },
    "b": {
      "ingredientAmounts": "2 Pump, 3 Pumps, 4 Pumps",
      "ingredientName": "White Chocolate",
      "ingredientSizes": "Small, Medium, Large"
    },
    "d": {
      "ingredientAmounts": "10 oz, 12 oz, 16 oz",
      "ingredientName": "Steamed Milk and Foam",
      "ingredientSizes": "Small, Medium, Large"
    }
  },
  "instructions": {
    "a": {
      "text": "Free pour milk into cup.  Top with 1/4 inch foam.  Make a circle with chocolate drizzle and use a thermometer to spread the chocolate into a flower pattern.",
      "type": "text"
    }
  },
  "name": "Congo Split",
  "temperature": "hot"
},

从上面的结构可以推断,ingredientsinstructions 字段可能包含多个元素...在下面的示例中使用 abc 设计。

我已按照示例代码片段使用 Angular Firestore:

在我的 recipes.service.ts 文件中,我有以下方法提供 Firestore[= 中数据的实时更新副本62=]:

  getRecipesFirestore() {
    this.recipesCollection = this.afs.collection('mission-cafe');
    this.recipesData = this.recipesCollection.valueChanges();
    return this.recipesData;
  }

home.ts 文件中调用该方法,返回食谱数据:

  ngOnInit() {

   [...]

    this.recipesData = this.recipesService.getRecipesFirestore();
  }

好消息是我可以使用模板文件中的 *ngFor 轻松显示此数据集的 most 的内容:

  <ion-card *ngFor="let item of recipesData | async">
     <ion-title>{{item.name}}</ion-title>
  </ion-card>

这适用于文档字段顶层的所有键。但是当我尝试显示 ingredientsinstructions 的子元素时,我得到的是 [object] 而不是内容。这并不奇怪。这是一个不起作用的例子。

  <ion-card *ngFor="let item of recipesData | async">
     <ion-title>{{item.name}}</ion-title>

     <div *ngFor="let ingred of item>                     < I was hoping to be able
         <ion-text>{{ingred.ingredientName}}</ion-text    < to iterate through elements
     </div>                                               <  of the ingredient array

  </ion-card>

所以问题:
我无法弄清楚获取食谱字段内地图内容的语法。

我可以想象解析 JSON(我在使用实时数据库时这样做过),但我希望利用模板文件暗示的使用 Firestore 简化的简单语法以上。

那里有语法教练吗?

在撰写本文时,唯一允许列出文档子集的 libraries/SDKs 是在“受信任的服务器环境”中使用的那些 Node.js, Java、PHP 等。请参阅 this document 了解更多信息。

Retrieving a list of collections is not possible with the mobile/web client libraries.

解决方法是将子集合名称存储在文档的字段(例如数组)中。 您可以参考此功能编辑您的 recipe.services.ts 功能:

constructor(private afs: AngularFirestore) { }

ngOnInit() {
  ...

    this.recipesCollection =afs.collection('mission-cafe');
    this.recipesData = this.recipesCollection.valueChanges();
    return this.recipesData;                                                                
}

访问特定“食谱”的成分子集:

this.subCollection = this.afs.collection('mission-cafe/'+id+'/ingredients');

您可以将数据收集到不同数组的子集合中,然后在 html 的 *ngFor 循环中使用它。

另请参阅 Firebase 文档,了解以下几点:

  1. Updating elements in an array

  2. Hierarchical model

所以我认为 Priyanka 试图告诉我的是准确的,但我花了很长时间才整理出来。需要了解的一个关键思想是,在 Firestore 中,奇数层是 Collections,偶数层是 Documents。总是。

但是,在文档中,可以有 字段 。这些字段可以包含 Arrays,而这些数组可以包含 maps。当然,这些地图可以包含 字符串 .

如果你保持跟踪,你有

Collection
  Document
    Collection
       Document   (As many as you want of the Coll/Doc layers)
         Field
            Map
               String: String
            Map
               String: String
            Array
               Map
                  String: String,
                  String: String
               Map
                (et cetera)

所以使用我的例子:

在我的例子中,每个 文档 都是一个食谱,其中包含一个 字段 的食谱组件,例如名称和温度。 instructions 和 ingredients 字段是 arrays of maps 包含多步信息,而其他字段是简单的东西,比如 name: "BlendedChaiCream" .

所以剩下的问题是如何让所有这些数据显示在应用程序中。这就是您希望发生的概念。

这是方法:

ngOnInit中我们获取集合,并订阅recipesInfo

ngOnInit() {

this.recipesCollection = this.afs.collection('mission-cafe');
this.recipesInfo = this.recipesCollection.snapshotChanges();

this.recipesInfo.subscribe((actionArray) => {
  this.recipesElements = actionArray.map((item) => ({
    id: item.payload.doc.id,
    ...item.payload.doc.data(),
    expanded: false
  }));
});

}

为新手解释一下...recipesElements 是模板文件(HTML 文件)将迭代的数组。所以我们用食谱文件的 ID 和所有其他食谱文件的 ID 加载它。这就是扩展运算符 ... 所做的。它代表所有其他数据。然后我再添加一个元素 expanded,我稍后会用它来决定是否应该在 ion-cards.

的手风琴显示中展开(打开)或折叠食谱

然后在模板文件中,我有这个:

<ion-card
  (click)="expandItem($event, false, item)"  <--- use this to toggle open/closed on accordion display
  *ngFor="let item of recipesElements">
  <ion-card-header>
      <ion-card-title>{{item.name}}
  </ion-card-header>
  <ion-card-content>
    <app-expandable expandHeight="6500px" [expanded]="item.expanded">

         [[[[insert formatting here for the display]]]]
         [[[[my formatting includes the individual fields]]]]

              item.notes
              item.image
              item.status
              and so on.

         [[[[ for instructions, I had an secondary *ngFor like this ]]]]

              <ion-item *ngFor="let ingred of item.ingredients">
         
         [[[[ and then refer to the individual ingredients as ]]]]

              <ion-grid>
                   <ion-row>
                        <ion-col> {{ingred.ingredientName}} </ion-col>
                        <ion-col> {{ingred.ingredientSizes}} </ion-col>
                        <ion-col> {{ingred.ingredientAmounts}} </ion-col>
                   </ion-row>
              <ion-grid>
          </ion-item>
     <ion-card>

所以这很简单。我只需要了解 Firestore 集合的结构,然后从中创建一个数组来迭代。