Угловой 6 |AngularFireDatabase - возвращает ключи и значения из объекта - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь понять, как получить данные из базы данных Firebase Realtime, используя Angular 6, AngularFireDatabase и Ionic 3. Существует много противоречивой информации, и приведенные здесь примеры / подходы не увенчались успехом.

Данные, которые я пытаюсь отобразить, структурированы как:

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;
    }

}

Службаназывается в компоненте.Я пробовал несколько способов здесь, но в основном я получаю идентификатор # из запроса, который работает надежно, а затем передаю его службе как так:

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 

и отображаемое значениерезультат заставляет меня чувствовать, что это близко?возможно ???

Вывод приложения - отображение обертки объекта?

Я пытаюсь вернуть «this.fields» как подписанный снимок объекта базы данных, который содержит ключ/ значение пары, которые могут быть отображены.Я не смог найти ничего, что работает за последние несколько дней поиска.Не может быть так сложно отображать поля из базы данных, верно?

Любое образование или советы с благодарностью!Я знаю, что мне нужно пройти долгий путь, чтобы набрать скорость и приветствовать все предложения по ресурсам!

1 Ответ

0 голосов
/ 08 октября 2018

Проблема в том, что код, заполняющий this.email$, не завершился к тому времени, как вы используете его в firebase.database().ref....Вот почему вы получаете некоторый результат, когда вы жестко его кодируете.

Решением будет использование оператора rxjs, например switchMap():

component :

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}
              }))
            )
        }));
  }
}

шаблон :

<code><hello name="{{ name }}"></hello>
<p>
  Start editing to see some magic happen :)
</p>
<h3><pre>{{ person$ | async | json }}

Модифицированную и рабочую версию вашего стекаблица можно найти здесь

...