【问题标题】:Angular 6 | AngularFireDatabase - return keys & values from object角 6 | AngularFireDatabase - 从对象返回键和值
【发布时间】:2018-10-04 14:59:07
【问题描述】:

我正在努力理解如何使用 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?

我试图将“this.fields”作为数据库对象的订阅快照返回,其中包含可以显示的键/值对。在过去几天的寻找中,我一直找不到任何有效的东西。显示数据库中的字段不会这么难吧?

非常感谢任何教育或提示!我知道我还有很长的路要走,以加快速度并欢迎所有关于资源的建议!

【问题讨论】:

  • 乍一看有些地方不对劲。在服务中:return {key, data}:我想你可能想像这样分解datareturn {key, ...data}this.fields = this.users.getData(this.uid2).subscribe();:你this.fields 是这样的订阅。试试this.users.getData(this.uid2).subscribe(users =&gt; this.fields = users)。如果您可以创建stackblitz,您可能会收到更多回复。
  • 谢谢蒂姆!我将深入修改订阅并创建一个堆栈闪电战
  • 剥离方法并将其放入堆栈闪电战中。取得了某种进展,在 stackblitz 中为空,但如果我对数据库路径进行硬编码,则会得到一个对象 - angular-firetortbexample.stackblitz.io

标签: angular firebase ionic-framework angularfire2


【解决方案1】:

问题是填充this.email$ 的代码在您使用firebase.database().ref... 时尚未完成。这就是为什么在硬编码时会得到一些结果。

解决方案是使用 rxjs 运算符,例如 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>

可以在 here 找到您的 stackblitz 的修改和工作版本

【讨论】:

  • 哇,谢谢蒂姆!我需要复习一些不熟悉的概念,但这要简单得多,也更容易理解。非常感谢!
  • 如何向 getData() 添加错误处理?我的一些用户无权访问该数据,我想处理错误并显示它,但不确定如何。顺便说一句,这也解决了我的问题。谢谢!!!
猜你喜欢
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
  • 1970-01-01
  • 2022-06-14
  • 1970-01-01
  • 1970-01-01
  • 2017-08-10
  • 1970-01-01
相关资源
最近更新 更多