0

I'm trying to retrieve data from Angularfire : "^5.0.0-rc0" using a service, and want to return the result to the component using this service, and the component should print the result from firebase to html file.

I am facing issue due to async retrieval of data from firebase, although I am getting proper response in console but don't know how to get the data in my component's html file.

Please note : FirebaseObjectObservable<any[]>; won't work in current version of angularfire, following are my files :

trip-data.service.ts :

import { Injectable } from '@angular/core';
declare var firebase: any;
import { Http, Response } from '@angular/http';
import { AngularFireDatabase, AngularFireObject } from 'angularfire2/database';
import { Observable} from 'rxjs/Observable';



@Injectable()
export class TripDataService {

finalItems;
public data: Array<any> =[];
public myData: any[] =[];
  constructor(db: AngularFireDatabase) {

    db.object('/').snapshotChanges().map(action => {
            this.finalItems = { ...action.payload.val() };
            return this.finalItems;
          }).subscribe(item => {
            console.log(item);
            this.myData = item;
            console.log(this.myData);
          }
          );
    }
}

list.component.ts :

import { Component, OnInit } from '@angular/core';
import { TripDataService } from '../trip-data.service';
import { AngularFireDatabase, AngularFireObject } from 'angularfire2/database';
import { Observable} from 'rxjs/Observable';

@Component({
  selector: 'app-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.css'],
  providers: [TripDataService]
})
export class ListComponent implements OnInit {
trips;
      constructor(service: TripDataService) {
            // this.trips = service();
            this.trips = service.myData;
            console.log(this.trips);
       }

      ngOnInit() {

      }

}
GauravA.
  • 35
  • 1
  • 9

3 Answers3

0

You're referencing a different myData in the component. It gets reassigned when you receive the data in your service. Have a method in your service return an observable instead and subscribe to that in your component. Or better yet, use the async pipe in your template.

funkizer
  • 4,626
  • 1
  • 18
  • 20
  • Can you show me how ? I am new to observable and subscribe functions and also how to use async in template ? It would be really helpful – GauravA. Oct 15 '17 at 10:24
  • Docs have a good example: https://github.com/angular/angularfire2/blob/master/docs/rtdb/objects.md – funkizer Oct 15 '17 at 10:31
  • I like to do stuff like
    Got {{ item.stuff }} here, async pipe handles subscribing and changeDetection triggering so I can use ChangeDetectionStrategy.OnPush!
    – funkizer Oct 15 '17 at 10:33
  • services are really not needed unless you do some side effects with the data, as AF2 is so simple to use :) – funkizer Oct 15 '17 at 10:35
  • But to your original code, you could move everything in the service 's constructor to a method getData. Then remove .subscribe out of it, and in the component you'd call this.service.getData().subscribe( data => this.data = data); – funkizer Oct 15 '17 at 10:42
  • But if you subscribe yourself like that, remember to unsubscribe in component's ngOnDestroy. Async pipe handles that for you aswell so it's a carefree solution – funkizer Oct 15 '17 at 10:43
  • I tried the above solutions you gave, but on moving subscribe code to component's constructor, it throws error that, "Property getData() does not exist on type 'TripDataService' " Following is my code : component file : `export class ListCompFirebasrComponent implements OnInit { trips; trip : any; constructor(service: TripDataService) { this.trips = service.getData().subscribe(item => { console.log(item); }); console.log(this.trips); } ngOnInit() { } }` – GauravA. Oct 15 '17 at 17:57
  • Glad to see you resolved it and seems you got what was perhaps the most important point in my long messy monologue lol - it's best practice to return an Observable from services and _never_ call subscribe in a service.ts. =) – funkizer Jan 26 '18 at 13:59
0

How about:

export class ListCompFirebasrComponent implements OnInit { trips; trip : any; constructor(private service: TripDataService) { this.trips = this.service.getData().subscribe(item => { console.log(item); }); console.log(this.trips); } ngOnInit() { } }

Does that help?

Bakr
  • 11
  • 2
0

As I mentioned earlier,that I wanted to post the response from firebase on my html page as soon as response was received, Thanks @toni for help. I solved it in following way :

trip-data.service.ts

import { Injectable, OnChanges, Input, SimpleChanges } from '@angular/core';
import { Http, Response } from '@angular/http';
import { AngularFireDatabase, AngularFireObject, AngularFireAction } from 'angularfire2/database';
import { Observable} from 'rxjs/Observable';
declare var firebase: any;
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/switchMap';



@Injectable()
export class TripDataService {

finalItems:any;
public data: Array<any> =[];
public myData: any[] =[];

constructor(db : AngularFireDatabase) {       
 this.finalItems = db.object('/').snapshotChanges().map(action => {
  return [ ...action.payload.val() ];
});
}
}

my component file:

import { Component, OnInit } from '@angular/core';
import { TripDataService } from '../trip-data.service';
import { AngularFireDatabase, AngularFireObject } from 'angularfire2/database';
import { Observable} from 'rxjs/Observable';

@Component({
  selector: 'app-list-comp-firebasr',
  templateUrl: './list-comp-firebasr.component.html',
  styleUrls: ['./list-comp-firebasr.component.css'],
  providers: [TripDataService]
})
export class ListCompFirebasrComponent implements OnInit {
trip_details;
responseArray;

  constructor(service: TripDataService) {
    service.finalItems.subscribe(item => {
            this.trip_details= item.filter(function(obj){
                return obj.trip_type == "Requested";
            });    
    });
  }

  ngOnInit() {
  }
}

And finally my html file :

<div>
   <h4>Requested Trips</h4>
     <ul *ngFor="let trip of trip_detials">
       <li>
       {{ trip.destination }}
       </li>
    </ul>
</div>
GauravA.
  • 35
  • 1
  • 9