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

Angular 2中Firebase数据获取与表格渲染问题求助

解决Angular 2中Firebase数据检索与表格填充问题

我来帮你一步步拆解解决这两个问题,从数据结构优化到代码实现逐一梳理:

一、无法通过密钥检索Firebase数据的解决方案

先看你提供的Firebase数据结构,EDI855下的Bill To、Email Id、Po Number是三个独立节点,每个节点下的子项都有自动生成的唯一密钥(比如-L9ac7clRzSVT-EfGxYv)。要通过这些密钥获取对应数据,你可以用AngularFire2的object方法精准定位节点:

1. 单个密钥数据检索(以Bill To为例)

先确保你已导入AngularFireDatabase并注入到组件中:

import { AngularFireDatabase } from 'angularfire2/database';

constructor(private db: AngularFireDatabase) {}

// 根据密钥获取单个Bill To数据
getSingleBillTo(key: string) {
  return this.db.object(`/EDI855/Bill To/${key}`).valueChanges();
}

// 在组件中调用并订阅数据
ngOnInit() {
  this.getSingleBillTo('-L9ac7clRzSVT-EfGxYv').subscribe(data => {
    console.log('Bill To数据:', data); // 输出"123456789"
  });
}

2. 关键优化:调整数据结构

你当前的结构把同一笔订单的三个字段拆分在不同节点,会导致后续关联数据、填充表格非常麻烦。更合理的做法是把每笔订单的所有字段放在同一个节点下,比如:

EDI855
  -L9ac7clRzSVT-EfGxYv:
    billTo: "123456789"
    emailId: "test@gmail.com"
    poNumber: "123456789"
  -L9acDp2k34qDpubJFr6:
    billTo: "123456780"
    emailId: "test1@gmail.com"
    poNumber: "VV002"

这样不仅能通过单个密钥直接获取整笔订单的所有数据,还能大幅简化表格填充逻辑。


二、遍历Firebase数据填充表格的解决方案

你说console能看到数据但表格不显示,大概率是异步数据处理不恰当或者模板绑定逻辑有误,下面分两种结构给出解决方案:

方案1:基于你当前的数据结构(不调整结构)

因为三个字段的子节点是独立的,需要先分别获取三个列表的数据,再按顺序关联合并:

组件代码

import { Component, OnInit } from '@angular/core';
import { AngularFireDatabase } from 'angularfire2/database';

@Component({
  selector: 'app-bill-table',
  templateUrl: './bill-table.component.html'
})
export class BillTableComponent implements OnInit {
  billToList: Array<{key: string, value: string}> = [];
  emailIdList: Array<{key: string, value: string}> = [];
  poNumberList: Array<{key: string, value: string}> = [];
  combinedData: Array<{billTo: string, emailId: string, poNumber: string}> = [];

  constructor(private db: AngularFireDatabase) {}

  ngOnInit(): void {
    // 获取Bill To数据(包含密钥)
    this.db.list('/EDI855/Bill To').snapshotChanges().subscribe(items => {
      this.billToList = items.map(item => ({
        key: item.key,
        value: item.payload.val() as string
      }));
      this.mergeData();
    });

    // 获取Email Id数据
    this.db.list('/EDI855/Email Id').snapshotChanges().subscribe(items => {
      this.emailIdList = items.map(item => ({
        key: item.key,
        value: item.payload.val() as string
      }));
      this.mergeData();
    });

    // 获取Po Number数据
    this.db.list('/EDI855/Po Number').snapshotChanges().subscribe(items => {
      this.poNumberList = items.map(item => ({
        key: item.key,
        value: item.payload.val() as string
      }));
      this.mergeData();
    });
  }

  // 合并三个列表的数据(假设三个列表的条目顺序对应)
  private mergeData(): void {
    if (this.billToList.length && this.emailIdList.length && this.poNumberList.length) {
      this.combinedData = this.billToList.map((billTo, index) => ({
        billTo: billTo.value,
        emailId: this.emailIdList[index].value,
        poNumber: this.poNumberList[index].value
      }));
    }
  }
}

模板代码(HTML)

<table border="1">
  <thead>
    <tr>
      <th>Bill To</th>
      <th>Email Id</th>
      <th>Po Number</th>
    </tr>
  </thead>
  <tbody>
    <!-- 用*ngFor遍历合并后的数据 -->
    <tr *ngFor="let item of combinedData">
      <td>{{ item.billTo }}</td>
      <td>{{ item.emailId }}</td>
      <td>{{ item.poNumber }}</td>
    </tr>
  </tbody>
</table>

方案2:基于优化后的 data structure(推荐)

调整结构后,获取数据和填充表格的逻辑会简单很多,还能避免数据关联出错的问题:

组件代码

import { Component, OnInit } from '@angular/core';
import { AngularFireDatabase } from 'angularfire2/database';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Component({
  selector: 'app-bill-table',
  templateUrl: './bill-table.component.html'
})
export class BillTableComponent implements OnInit {
  // 用Observable存储数据,配合async管道自动处理异步
  orders$: Observable<Array<{key: string, billTo: string, emailId: string, poNumber: string}>>;

  constructor(private db: AngularFireDatabase) {}

  ngOnInit(): void {
    this.orders$ = this.db.list('/EDI855').snapshotChanges().pipe(
      map(items => items.map(item => ({
        key: item.key,
        ...item.payload.val() as {billTo: string, emailId: string, poNumber: string}
      })))
    );
    // 这里console.log能看到数据,是因为Observable订阅后才会触发,而async管道会自动处理
    this.orders$.subscribe(orders => console.log('订单数据:', orders));
  }
}

模板代码(HTML)

<table border="1">
  <thead>
    <tr>
      <th>Bill To</th>
      <th>Email Id</th>
      <th>Po Number</th>
    </tr>
  </thead>
  <tbody>
    <!-- 用async管道直接订阅Observable,数据返回后自动渲染 -->
    <tr *ngFor="let order of orders$ | async">
      <td>{{ order.billTo }}</td>
      <td>{{ order.emailId }}</td>
      <td>{{ order.poNumber }}</td>
    </tr>
  </tbody>
</table>

为什么之前表格不显示?

最常见的原因是:

  1. 数据是异步获取的,模板渲染时数据还未返回,导致*ngFor遍历空数组
  2. 模板绑定的变量名和组件中的变量名不一致
  3. 没有正确处理Firebase返回的快照数据(比如只取了valueChanges()而没保留密钥,或者没正确解析数据结构)

用async管道是最省心的方式,它会自动等待数据返回后再渲染表格,避免异步时序问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:35:01