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"
},
从上面的结构可以推断,ingredients 和 instructions 字段可能包含多个元素...在下面的示例中使用 a、b 和 c 设计。
我已按照示例代码片段使用 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>
这适用于文档字段顶层的所有键。但是当我尝试显示 ingredients 或 instructions 的子元素时,我得到的是 [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 文档,了解以下几点:
所以我认为 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 集合的结构,然后从中创建一个数组来迭代。
这道题的设置很长。最后,我要求语法指导,如果你滚动到设置的末尾,你会看到这个问题。
我有一个 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"
},
从上面的结构可以推断,ingredients 和 instructions 字段可能包含多个元素...在下面的示例中使用 a、b 和 c 设计。
我已按照示例代码片段使用 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>
这适用于文档字段顶层的所有键。但是当我尝试显示 ingredients 或 instructions 的子元素时,我得到的是 [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 文档,了解以下几点:
所以我认为 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 集合的结构,然后从中创建一个数组来迭代。