You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular Firestore 如何展示文档中内嵌映射类型字段的内容

Angular 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 中实时更新的食谱数据:

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

在 home.ts 文件中调用该方法获取 recipesData:

ngOnInit() {
  // 其他逻辑省略
  this.recipesData = this.recipesService.getRecipesFirestore();
}

目前我可以通过模板中的 *ngFor 指令正常展示大部分顶层字段的内容:

<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">                     
       <ion-text>{{ingred.ingredientName}}</ion-text
   </div>
</ion-card>

核心问题:
我找不到正确的语法来访问食谱字段内嵌映射对象的内容。我知道可以手动解析 JSON(之前使用实时数据库时就是这么做的),但我希望能用上 Firestore 配套的简洁模板语法来实现该需求,请问正确的写法是什么?

解决方案

Angular 6及以上版本内置了keyvalue管道,可直接在模板中遍历对象类型的字段,无需手动做JSON解析,适配Firestore返回的映射结构,正确写法如下:

模板代码

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

  <!-- 遍历ingredients映射 -->
  <div *ngFor="let ingredEntry of item.ingredients | keyvalue">
    <!-- ingredEntry.key对应a/b/d这类键,ingredEntry.value对应具体的配料对象 -->
    <ion-text>{{ingredEntry.value.ingredientName}}</ion-text>
    <p>可选规格:{{ingredEntry.value.ingredientSizes}}</p>
    <p>对应用量:{{ingredEntry.value.ingredientAmounts}}</p>
  </div>

  <!-- 遍历instructions映射同理 -->
  <div *ngFor="let instructionEntry of item.instructions | keyvalue">
    <p>操作步骤:{{instructionEntry.value.text}}</p>
  </div>
</ion-card>

可选:自定义排序规则

如果需要按键的顺序固定排序,可以给keyvalue管道传入自定义排序函数:

  1. 在home.ts中添加排序方法
import { KeyValue } from '@angular/common';

// 按字母升序排序键
sortByKey = (a: KeyValue<string, any>, b: KeyValue<string, any>): number => {
  return a.key.localeCompare(b.key);
}
  1. 模板中调用排序方法
<div *ngFor="let ingredEntry of item.ingredients | keyvalue:sortByKey">

低版本Angular兼容方案

如果你的Angular版本低于6,没有内置keyvalue管道,可以自行封装简易的自定义管道:

  1. 新建map-values.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'mapValues'
})
export class MapValuesPipe implements PipeTransform {
  transform(value: Record<string, any>): any[] {
    return value ? Object.values(value) : [];
  }
}
  1. 在对应模块的declarations中引入该管道后,模板中直接使用:
<div *ngFor="let ingred of item.ingredients | mapValues">
  <ion-text>{{ingred.ingredientName}}</ion-text>
</div>

内容的提问来源于stack exchange,提问作者Paul Mullen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 16:36:01