Angular 6 | AngularFireDatabase - return 来自对象的键和值
Angular 6 | AngularFireDatabase - return keys & values from object
我正在努力理解如何使用 Angular 6、AngularFireDatabase 和使用 Ionic 3 从 Firebase 实时数据库获取数据。有很多相互矛盾的信息和使用示例/方法在这里张贴没有成功。
我要显示的数据结构如下:
ID#
- title: "James N"
- email: "j@n.com"
- numitems: "2"
我已经在服务中构造了原始调用 (profile.ts)
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { AngularFireDatabase } from '@angular/fire/database';
import { map, catchError } from 'rxjs/operators';
@Injectable()
export class Users{
details: Observable<any>;
id: string;
constructor (public db: AngularFireDatabase){};
// console.log("uid in getdata: " + this.uid2);
getData(id): Observable<any> {
this.details = this.db.list('/ftuserprofiles/'+this.id).snapshotChanges()
.pipe(map(items => {
return items.map(a => {
const data = a.payload.val();
const key = a.payload.key;
return {key, data};
});
}));
console.log('users.getdata() details: ' + this.details)
return this.details;
}
}
在组件中调用服务。我在这里尝试了多种方法,但基本上我是从可靠工作的查询中获取 ID#,然后将其传递给服务:
import { Component } from '@angular/core';
import { Users } from './profile';
import { NavController, NavParams } from 'ionic-angular';
import { Intercom } from '@ionic-native/intercom';
import { AuthService } from '../../providers/auth/auth';
import { DataProvider } from '../../providers/data/data';
import * as firebase from 'firebase';
// import { HttpClient, HttpClientModule } from '@angular/common/http';
import { AngularFireDatabase } from '@angular/fire/database';
import { Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { throwError } from "rxjs";
import 'rxjs/add/observable/fromPromise';
@Component({
selector: 'page-garden',
templateUrl: 'garden.html',
})
export class GardenPage {
public items: any [] = [];
public itemRef;
public email$;
public cdQ4;
public title: string="";
public numbeds:string="";
public address:string="";
public email:string="";
public fields;
public id: string="";
uid2;
constructor(
public navCtrl: NavController,
// public http: HttpClient,
public navParams: NavParams,
private auth: AuthService,
private intercom: Intercom,
private data: DataProvider,
private db: AngularFireDatabase,
public users: Users
)
{
this.getUID();
console.log('cid from getUID-constructor : ' + this.uid2);
this.fields = this.users.getData(this.uid2).subscribe();
console.log('this.fields : ', this.fields);
console.log('this.fields : ' + this.fields.key);
}
getUID() {
this.email$ = this.auth.getEmailOnly();
this.cdQ3 = firebase.database().ref('/ftuserprofiles')
.orderByChild('email')
.equalTo(this.email$);
this.details = this.cdQ3.once('value').then((snapshot) => {
this.userDeets = [];
snapshot.forEach( snap => {
this.uid2 = snap.key;
console.log('cid from getUID-garden : ' + this.uid2);
return false;
});
});
return this.uid2;
}
ionViewDidLoad() {
console.log('ionViewDidLoad GardenPage');
this.getUID();
this.email$ = this.auth.getEmailOnly();
this.cdQ4 = this.users.getData(this.uid2);
this.address = this.fields['address'];
this.title = this.fields.title;
console.log('title ' + this.title);
}
}
最后展示一下,我(在对管道进行了大量痛苦的研究之后)将以下内容作为测试来展示我得到的结果:
<ion-header>
......
</ion-header>
<ion-content padding>
......
<ion-list>
<ion-item *ngFor="let item of fields | keyvalue">
{{ item.key }} - {{ item.value }}
</ion-item>
</ion-list>
</ion-content>
我得到以下控制台输出:
[app-scripts] [07:34:01] console.log: Ionic Native: deviceready event fired after 1588 ms
[app-scripts] [07:34:02] console.log: signed in user:
[app-scripts] [07:34:02] console.log: jeremy@avalow.com
[app-scripts] [07:34:02] console.log: intercom register user
[app-scripts] [07:34:02] console.log: intercom register for push
[app-scripts] [07:34:03] console.log: cid from getUID-constructor : undefined
[app-scripts] [07:34:03] console.log: users.getdata() details: [object Object]
[app-scripts] [07:34:03] console.log: this.fields : undefined
[app-scripts] [07:34:03] console.log: ionViewDidLoad GardenPage
[app-scripts] [07:34:03] console.log: users.getdata() details: [object Object]
[app-scripts] [07:34:03] console.log: title undefined
[app-scripts] [07:34:03] console.log: jeremy@avalow.com
[app-scripts] [07:34:03] console.log: cid from getUID-garden : 2a2a18f2-49e6-3daf-9208-ef3f67c15e12
而且现在显示的结果让我觉得很接近?也许???
App output - displaying object wrapper?
我正在尝试 return "this.fields" 作为包含可以显示的键/值对的数据库对象的订阅快照。在过去几天的寻找中,我一直找不到任何有用的东西。显示数据库中的字段不会这么难,对吧?
非常感谢任何教育或提示!我知道我要加快速度还有很长的路要走,欢迎所有资源建议!
问题是当您在 firebase.database().ref...
中使用它时,填充 this.email$
的代码尚未完成。这就是为什么当你硬编码时你会得到一些结果。
一个解决方案是使用像 switchMap()
:
这样的 rxjs 运算符
分量:
import { Component } from '@angular/core';
import { AngularFireDatabase, AngularFireObject, AngularFireAction } from '@angular/fire/database';
import { Observable, of } from 'rxjs';
import { map, catchError, tap, switchMap } from 'rxjs/operators';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Firebase Data Test';
public email$: Observable<string>;
public person$: Observable<any>;
constructor(private db: AngularFireDatabase) { }
ngOnInit() {
// I'm guessing this is an observable in your code
// using of() for simplicity
// this.email$ = this.auth.getEmailOnly();
this.email$ = of('j@j.com');
this.person$ = this.getData();
}
getData(): Observable<any> {
return this.email$.pipe(
// switchMap returns a different observable for eacht emitted value by the source (this.email$)
switchMap(email => {
// no need to use native firebase api, can be done with angularfire
return this.db.list('ftuserprofiles', ref =>
ref.orderByChild('email')
.equalTo(email)
.limitToFirst(1))
.snapshotChanges()
.pipe(
map(actions => actions.map(action => {
const key = action.payload.key;
const data = action.payload.val();
return {key, ...data}
}))
)
}));
}
}
模板:
<hello name="{{ name }}"></hello>
<p>
Start editing to see some magic happen :)
</p>
<h3><pre>{{ person$ | async | json }}</pre></h3>
可以找到您的 stackblitz 的修改版和工作版 here
我正在努力理解如何使用 Angular 6、AngularFireDatabase 和使用 Ionic 3 从 Firebase 实时数据库获取数据。有很多相互矛盾的信息和使用示例/方法在这里张贴没有成功。
我要显示的数据结构如下:
ID#
- title: "James N"
- email: "j@n.com"
- numitems: "2"
我已经在服务中构造了原始调用 (profile.ts)
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { AngularFireDatabase } from '@angular/fire/database';
import { map, catchError } from 'rxjs/operators';
@Injectable()
export class Users{
details: Observable<any>;
id: string;
constructor (public db: AngularFireDatabase){};
// console.log("uid in getdata: " + this.uid2);
getData(id): Observable<any> {
this.details = this.db.list('/ftuserprofiles/'+this.id).snapshotChanges()
.pipe(map(items => {
return items.map(a => {
const data = a.payload.val();
const key = a.payload.key;
return {key, data};
});
}));
console.log('users.getdata() details: ' + this.details)
return this.details;
}
}
在组件中调用服务。我在这里尝试了多种方法,但基本上我是从可靠工作的查询中获取 ID#,然后将其传递给服务:
import { Component } from '@angular/core';
import { Users } from './profile';
import { NavController, NavParams } from 'ionic-angular';
import { Intercom } from '@ionic-native/intercom';
import { AuthService } from '../../providers/auth/auth';
import { DataProvider } from '../../providers/data/data';
import * as firebase from 'firebase';
// import { HttpClient, HttpClientModule } from '@angular/common/http';
import { AngularFireDatabase } from '@angular/fire/database';
import { Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { throwError } from "rxjs";
import 'rxjs/add/observable/fromPromise';
@Component({
selector: 'page-garden',
templateUrl: 'garden.html',
})
export class GardenPage {
public items: any [] = [];
public itemRef;
public email$;
public cdQ4;
public title: string="";
public numbeds:string="";
public address:string="";
public email:string="";
public fields;
public id: string="";
uid2;
constructor(
public navCtrl: NavController,
// public http: HttpClient,
public navParams: NavParams,
private auth: AuthService,
private intercom: Intercom,
private data: DataProvider,
private db: AngularFireDatabase,
public users: Users
)
{
this.getUID();
console.log('cid from getUID-constructor : ' + this.uid2);
this.fields = this.users.getData(this.uid2).subscribe();
console.log('this.fields : ', this.fields);
console.log('this.fields : ' + this.fields.key);
}
getUID() {
this.email$ = this.auth.getEmailOnly();
this.cdQ3 = firebase.database().ref('/ftuserprofiles')
.orderByChild('email')
.equalTo(this.email$);
this.details = this.cdQ3.once('value').then((snapshot) => {
this.userDeets = [];
snapshot.forEach( snap => {
this.uid2 = snap.key;
console.log('cid from getUID-garden : ' + this.uid2);
return false;
});
});
return this.uid2;
}
ionViewDidLoad() {
console.log('ionViewDidLoad GardenPage');
this.getUID();
this.email$ = this.auth.getEmailOnly();
this.cdQ4 = this.users.getData(this.uid2);
this.address = this.fields['address'];
this.title = this.fields.title;
console.log('title ' + this.title);
}
}
最后展示一下,我(在对管道进行了大量痛苦的研究之后)将以下内容作为测试来展示我得到的结果:
<ion-header>
......
</ion-header>
<ion-content padding>
......
<ion-list>
<ion-item *ngFor="let item of fields | keyvalue">
{{ item.key }} - {{ item.value }}
</ion-item>
</ion-list>
</ion-content>
我得到以下控制台输出:
[app-scripts] [07:34:01] console.log: Ionic Native: deviceready event fired after 1588 ms
[app-scripts] [07:34:02] console.log: signed in user:
[app-scripts] [07:34:02] console.log: jeremy@avalow.com
[app-scripts] [07:34:02] console.log: intercom register user
[app-scripts] [07:34:02] console.log: intercom register for push
[app-scripts] [07:34:03] console.log: cid from getUID-constructor : undefined
[app-scripts] [07:34:03] console.log: users.getdata() details: [object Object]
[app-scripts] [07:34:03] console.log: this.fields : undefined
[app-scripts] [07:34:03] console.log: ionViewDidLoad GardenPage
[app-scripts] [07:34:03] console.log: users.getdata() details: [object Object]
[app-scripts] [07:34:03] console.log: title undefined
[app-scripts] [07:34:03] console.log: jeremy@avalow.com
[app-scripts] [07:34:03] console.log: cid from getUID-garden : 2a2a18f2-49e6-3daf-9208-ef3f67c15e12
而且现在显示的结果让我觉得很接近?也许???
App output - displaying object wrapper?
我正在尝试 return "this.fields" 作为包含可以显示的键/值对的数据库对象的订阅快照。在过去几天的寻找中,我一直找不到任何有用的东西。显示数据库中的字段不会这么难,对吧?
非常感谢任何教育或提示!我知道我要加快速度还有很长的路要走,欢迎所有资源建议!
问题是当您在 firebase.database().ref...
中使用它时,填充 this.email$
的代码尚未完成。这就是为什么当你硬编码时你会得到一些结果。
一个解决方案是使用像 switchMap()
:
分量:
import { Component } from '@angular/core';
import { AngularFireDatabase, AngularFireObject, AngularFireAction } from '@angular/fire/database';
import { Observable, of } from 'rxjs';
import { map, catchError, tap, switchMap } from 'rxjs/operators';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Firebase Data Test';
public email$: Observable<string>;
public person$: Observable<any>;
constructor(private db: AngularFireDatabase) { }
ngOnInit() {
// I'm guessing this is an observable in your code
// using of() for simplicity
// this.email$ = this.auth.getEmailOnly();
this.email$ = of('j@j.com');
this.person$ = this.getData();
}
getData(): Observable<any> {
return this.email$.pipe(
// switchMap returns a different observable for eacht emitted value by the source (this.email$)
switchMap(email => {
// no need to use native firebase api, can be done with angularfire
return this.db.list('ftuserprofiles', ref =>
ref.orderByChild('email')
.equalTo(email)
.limitToFirst(1))
.snapshotChanges()
.pipe(
map(actions => actions.map(action => {
const key = action.payload.key;
const data = action.payload.val();
return {key, ...data}
}))
)
}));
}
}
模板:
<hello name="{{ name }}"></hello>
<p>
Start editing to see some magic happen :)
</p>
<h3><pre>{{ person$ | async | json }}</pre></h3>
可以找到您的 stackblitz 的修改版和工作版 here