AngularFire2 查询列表获取子值

AngularFire2 Query List Get Child Values

我有以下数据结构:

{
 "users" : {
    "AXLKSD9ASLKDJJ0991" : {
      "authType" : "ap1",
      "enabled" : true,
      "color" : "red"
    },
    "A778ASDUASDJ8AS8DA" : {
      "authType" : "ap1",
      "enabled" : true,
      "color" : "blue"
    },
    "ASD88ASD8ASD8HAS8D" : {
      "authType" : "ap2",
      "enabled" : true,
      "color" : "red"
    }
  }
}

我创建了一个专用于 Firebase 的服务,它有以下方法。这成功地 return 将用户添加到我的组件中:

firebase.service.ts:

userList: FirebaseListObservable<any[]>;

getUsersByAuthType(authType: string) {
  return this.userList = this.afDb.list('/users', {
    preserveSnapshot: true,
    query: {
        orderByChild: 'authProvider',
        equalTo: authType
    }
  });
}

admin.component.ts:

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

import { FirebaseService } from '../services/firebase.service';

@Component({
  selector: 'app-administration',
  templateUrl: './admin.component.html',
  styleUrls: ['./admin.component.css']
})
export class AdministrationComponent implements OnInit {
  usersData: any;

  constructor(
      private firebaseService: FirebaseService
  ) { }

  ngOnInit() {
    this.usersData = this.firebaseService.getUsersByAuthType('ap1');
  }

}

admin.component.html:

<h2>test 1</h2>
<ul *ngFor="let user of (usersData | async)">
<li>{{ user.enabled }}</li>
</ul>

<br /><br /><br />

<h2>test 2</h2>
{{ usersData | async | json }}

<br /><br /><br />

<h2>test 3</h2>
<ul *ngFor="let user of (usersData | async)">
<li>{{ user.key }}</li>
</ul>

"test 1" 没有显示任何内容..

"test 2" 显示整个 returned json 对象:

{ "authType" : "ap1", "enabled" : true, "color" : "red" }, { "authType" : "ap1", "enabled" : true, "color" : "blue" }

"test 3" 给我看钥匙。

我尝试了很多其他方法但没有成功。参考文档表明我正在做的是好的

https://github.com/angular/angularfire2/blob/master/docs/4-querying-lists.md

想法?

更新

我还在 admin.component.html 中添加了以下内容:

<br /><br /><br />

<h2>test 4</h2>
<ul *ngFor="let user of (usersData | async)">
<li>{{ (user | json) }}</li>
</ul>

这也导致渲染页面中出现以下输出:

更新 #2

总结提出的一些建议...

<ul *ngFor="let user of (usersData | async)">
<li>{{ user[user.key].enabled }}</li>
</ul>

<ul *ngFor="let user of (usersData | async)">
<li>{{ user[user.key]?.enabled }}</li>
</ul>

这些都没有 returned 任何东西,也没有记录错误。

以下内容很有趣:

<ul *ngFor="let user of (usersData | async)">
<li>{{ user.val }}</li>
</ul>

这会在组件中呈现以下内容:

更新#3

有人建议将调用映射到我的 firebase 服务,如下所示:

ngOnInit() {
    this.usersData = this.firebaseService.getUsersByAuthType('ap1')
                               .map(res => res.json());
}

然后更新我的组件视图如下:

<ul *ngFor="let user of (usersData | async)">
  <li>{{ user?.enabled }}</li>
</ul>

这导致了以下错误:

ERROR TypeError: res.json is not a function
    at MapSubscriber.project (administration.component.ts:26)
    at MapSubscriber.webpackJsonp.../../../../rxjs/operator/map.js.MapSubscriber._next (map.js:77)
    at MapSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber.next (Subscriber.js:89)
    at SwitchMapSubscriber.webpackJsonp.../../../../rxjs/operator/switchMap.js.SwitchMapSubscriber.notifyNext (switchMap.js:124)
    at InnerSubscriber.webpackJsonp.../../../../rxjs/InnerSubscriber.js.InnerSubscriber._next (InnerSubscriber.js:23)
    at InnerSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber.next (Subscriber.js:89)
    at Notification.webpackJsonp.../../../../rxjs/Notification.js.Notification.observe (Notification.js:32)
    at QueueAction.webpackJsonp.../../../../rxjs/operator/observeOn.js.ObserveOnSubscriber.dispatch (observeOn.js:87)
    at QueueAction.webpackJsonp.../../../../rxjs/scheduler/AsyncAction.js.AsyncAction._execute (AsyncAction.js:111)
    at QueueAction.webpackJsonp.../../../../rxjs/scheduler/QueueAction.js.QueueAction.execute (QueueAction.js:33)

我也尝试过将整个用户数据转储出来:

<h3>The whole lot</h3>
{{ usersData }}

这呈现:

[object Object]

同样值得分享的是,当我 console.log 什么 firebase 服务 returns 时,它返回为:

[数据快照,数据快照]

如果我展开它,你可以清楚地看到两个数组元素及其键属性,但是子节点不是立即可见的,而是深埋在结构中:

在网上看了一些资料后,我似乎需要创建一个自定义管道来进行转换,但我不确定该怎么做。我看过的例子,首先是有错误,不能编译,但也不是很清楚它是如何工作的。

我走在正确的轨道上吗?

我仍然不明白为什么 "test 4" 呈现的正是我所期望和需要的,我就是无法通过属性名称(例如 enabled、authType 等)访问它?

更新 #4

我已将 admin.component.html 更新为:

<h3>Test 5</h3>
<ng-container *ngIf="usersData != null && usersData.length !== 0">
  <ul *ngFor="let user of usersData">
    <li>{{ user?.enabled }}</li>
  </ul>
</ng-container>

我已经更新了 admin.component.ts ngOnInit 并且还从@angular/core:

导入了 markForCheck
  ngOnInit() {
    this.usersData = this.firebaseService.getUsersByAuthType('ap1')
      .map(res => res.json())
      .subscribe(result => {
        this.usersData = result;
        this.ref.markForCheck();
      });
  }

控制台提供以下见解:

AdminComponent.html:32 ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
    at NgForOf.webpackJsonp.../../../common/@angular/common.es5.js.NgForOf.ngOnChanges (common.es5.js:1659)
    at checkAndUpdateDirectiveInline (core.es5.js:10831)
    at checkAndUpdateNodeInline (core.es5.js:12330)
    at checkAndUpdateNode (core.es5.js:12269)
    at debugCheckAndUpdateNode (core.es5.js:13130)
    at debugCheckDirectivesFn (core.es5.js:13071)
    at Object.eval [as updateDirectives] (AdministrationComponent.html:32)
    at Object.debugUpdateDirectives [as updateDirectives] (core.es5.js:13056)
    at checkAndUpdateView (core.es5.js:12236)
    at callViewAction (core.es5.js:12601)

core.es5.js:1020 ERROR TypeError: res.json is not a function
    at MapSubscriber.project (administration.component.ts:30)
    at MapSubscriber.webpackJsonp.../../../../rxjs/operator/map.js.MapSubscriber._next (map.js:77)
    at MapSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber.next (Subscriber.js:89)
    at SwitchMapSubscriber.webpackJsonp.../../../../rxjs/operator/switchMap.js.SwitchMapSubscriber.notifyNext (switchMap.js:124)
    at InnerSubscriber.webpackJsonp.../../../../rxjs/InnerSubscriber.js.InnerSubscriber._next (InnerSubscriber.js:23)
    at InnerSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber.next (Subscriber.js:89)
    at Notification.webpackJsonp.../../../../rxjs/Notification.js.Notification.observe (Notification.js:32)
    at QueueAction.webpackJsonp.../../../../rxjs/operator/observeOn.js.ObserveOnSubscriber.dispatch (observeOn.js:87)
    at QueueAction.webpackJsonp.../../../../rxjs/scheduler/AsyncAction.js.AsyncAction._execute (AsyncAction.js:111)
    at QueueAction.webpackJsonp.../../../../rxjs/scheduler/QueueAction.js.QueueAction.execute (QueueAction.js:33)

如有任何帮助,我们将不胜感激。

试试这个:

user[user.key].enabled

问题出在结果的类型上。在调用订阅或 "async":

之前尝试映射结果
ngOnInit() {
    this.usersData = this.firebaseService.getUsersByAuthType('ap1')
                               .map(res => res.json());
}

那么你不需要| json

你现在可以走了:

<ul *ngFor="let user of (usersData | async)">
     <li>{{ user?.enabled }}</li>
</ul>

使用同步而不是异步:

users: any;

constructor(private ref: ChangeDetectorRef) {}

ngOnInit() {
    this.usersData = this.firebaseService.getUsersByAuthType('ap1')
                    .map(res => res.json()).subscribe(result => { 
                       users = result.users; 
                       this.ref.markForCheck();
                    });
}


<ng-container *ngIf="user != null && user.length !== 0">
   <ul *ngFor="let user of user">
        <li>{{ user?.enabled }}</li>
   </ul>
</ng-container>

您现在可以在订阅内设置一个调试器,以显示您正在接收的数据类型。实际上,它必须起作用。

所以问题归结为 preserveSnapshot 选项。

原始 firebase.service.ts 片段:

userList: FirebaseListObservable<any[]>;

getUsersByAuthType(authType: string) {
  return this.userList = this.afDb.list('/users', {
    preserveSnapshot: true,
    query: {
        orderByChild: 'authProvider',
        equalTo: authType
    }
  });
}

我需要放弃 preserveSnapshot: true 并将其设置为 false

admin.component.ts(无变化):

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

import { FirebaseService } from '../services/firebase.service';

@Component({
  selector: 'app-administration',
  templateUrl: './admin.component.html',
  styleUrls: ['./admin.component.css']
})
export class AdministrationComponent implements OnInit {
  usersData: any;

  constructor(
      private firebaseService: FirebaseService
  ) { }

  ngOnInit() {
    this.usersData = this.firebaseService.getUsersByAuthType('ap1');
  }
}

admin.component.html(无变化):

<ul *ngFor="let user of (usersData | async)">
<li>{{ user.enabled }}</li>
</ul>

组件按预期正确呈现。不太确定 preserveSnapshot: true 是组件 html 的问题,但确实如此。

如果有人知道为什么会这样,我很想知道。