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>
这也导致渲染页面中出现以下输出:
- { "authType" : "ap1", "enabled" : 真, "color" : "red" }
- { "authType" : "ap1", "enabled" : 真, "color" : "blue" }
更新 #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>
这会在组件中呈现以下内容:
- function () { (0, validation.validateArgCount)('DataSnapshot.val', 0, 0, arguments.length); return this.node.val(); }
- function () { (0, validation.validateArgCount)('DataSnapshot.val', 0, 0, arguments.length); return this.node.val(); }
更新#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 时,它返回为:
[数据快照,数据快照]
如果我展开它,你可以清楚地看到两个数组元素及其键属性,但是子节点不是立即可见的,而是深埋在结构中:
- [数据快照,数据快照]
- 0:数据快照
- index_ : 路径索引
- 键:“23123123123123”
- node_ : 子节点
- 比较器_:函数NAME_COMPARATOR(左,右)
- root_: LLRBNode
- 颜色:假
- 键:"enabled"
- 左:LLRBNode
- 右:LLRBNode
- 值:叶节点
- lazyHash_: null
- priorityNode_: ChildrenNode
- 值_: "true"
- 原型:对象
- 原型:对象
- ref : 参考
- ref_:引用
- 原型:对象
- 1:数据快照
- 长度:2
- 原型:数组(0)
在网上看了一些资料后,我似乎需要创建一个自定义管道来进行转换,但我不确定该怎么做。我看过的例子,首先是有错误,不能编译,但也不是很清楚它是如何工作的。
我走在正确的轨道上吗?
我仍然不明白为什么 "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 的问题,但确实如此。
如果有人知道为什么会这样,我很想知道。
我有以下数据结构:
{
"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>
这也导致渲染页面中出现以下输出:
- { "authType" : "ap1", "enabled" : 真, "color" : "red" }
- { "authType" : "ap1", "enabled" : 真, "color" : "blue" }
更新 #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>
这会在组件中呈现以下内容:
- function () { (0, validation.validateArgCount)('DataSnapshot.val', 0, 0, arguments.length); return this.node.val(); }
- function () { (0, validation.validateArgCount)('DataSnapshot.val', 0, 0, arguments.length); return this.node.val(); }
更新#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 时,它返回为:
[数据快照,数据快照]
如果我展开它,你可以清楚地看到两个数组元素及其键属性,但是子节点不是立即可见的,而是深埋在结构中:
- [数据快照,数据快照]
- 0:数据快照
- index_ : 路径索引
- 键:“23123123123123”
- node_ : 子节点
- 比较器_:函数NAME_COMPARATOR(左,右)
- root_: LLRBNode
- 颜色:假
- 键:"enabled"
- 左:LLRBNode
- 右:LLRBNode
- 值:叶节点
- lazyHash_: null
- priorityNode_: ChildrenNode
- 值_: "true"
- 原型:对象
- 原型:对象
- ref : 参考
- ref_:引用
- 原型:对象
- 1:数据快照
- 长度:2
- 原型:数组(0)
- 0:数据快照
在网上看了一些资料后,我似乎需要创建一个自定义管道来进行转换,但我不确定该怎么做。我看过的例子,首先是有错误,不能编译,但也不是很清楚它是如何工作的。
我走在正确的轨道上吗?
我仍然不明白为什么 "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 的问题,但确实如此。
如果有人知道为什么会这样,我很想知道。