0

I'm fetching data from Firebase with Angular 2 using Observables, but, even if i get the result from the http call, i can't map the returned object on my entity.

I want to map into an Array of Recipe. A recipe is:

export class Recipe {
    constructor(public name: string,
        public description: string,
        public imagePath: string,
        public ingredients: Ingredient[]) {
    }
}

The component class that contains the Array of Recipes and the first call to the service responsible of fetching data plus the subscriber is:

export class RecipeListComponent implements OnInit {
  recipes: Recipe[] = [];

  constructor(private recipeService: RecipeService) { }

  ngOnInit() {
    this.recipes = this.recipeService.getRecipes();
    this.recipeService.recipesChanged.subscribe(
      (recipes: Recipe[]) => this.recipes = recipes
    );
  }
}

While the method for fetching data in the service is:

  fetchData() {
    return this.http.get('https://...firebaseio.com/...json')
      .map((response: Response) => response.json())
      .subscribe(
      (data: Recipe[]) => {
        this.recipes = data;
        console.log(data);
        this.recipesChanged.emit(this.recipes);
      });

Data is correctly retrieved, but is not cast on my Recipe[], infact the returned object is in this form:

[object Object],[object Object]
   [
      0: {
         [functions]: ,
         __proto__: { },
         description: "Gioco",
         imagePath: "http://....png",
         ingredients: [
            0: {
               [functions]: ,
               __proto__: { },
               amount: 50,
               name: "Silicone",
               Symbol(observable)_g.ds6ymh8xmrz: undefined,
               Symbol(rxSubscriber)_h.ds6ymh8xmrz: undefined
            },
            1: {
               [functions]: ,
               __proto__: { },
               amount: 30,
               name: "Plastica",
               Symbol(observable)_g.ds6ymh8xmrz: undefined,
               Symbol(rxSubscriber)_h.ds6ymh8xmrz: undefined
            },
            length: 2
         ],
         name: "Lego",
         Symbol(observable)_g.ds6ymh8xmrz: undefined,
         Symbol(rxSubscriber)_h.ds6ymh8xmrz: undefined
      },
      1: {
         [functions]: ,
         __proto__: { },
         description: "Peluche",
         imagePath: "http://....png",
         name: "Orsacchiotto",
         Symbol(observable)_g.ds6ymh8xmrz: undefined,
         Symbol(rxSubscriber)_h.ds6ymh8xmrz: undefined
      },
      length: 2
   ]

How can it be solved?

Thanks in advance

1
  • Firebase does not store data as arrays, so the HTTP response will be a JSON object. And if you are going to use a simple cast, you should use an interface - not a class. Commented Mar 25, 2017 at 23:38

1 Answer 1

3

Output() variables are not intended to use in services, you should map the response and return the Observable as such

fetchData() :Observable<Recipes> {
    return this.http.get('https://...firebaseio.com/...json')
      .map((response: Response) => <Recipe[]>response.json())
      });

In your onInit

this.recipeService.getRecipes().subscribe(recipes => {
       this.recipes = recipes;
});

Also, when you are using reference types to serve as models use interfaces

export interface Recipe {
        name: string;
        description: string;
        imagePath: string;
        ingredients: Ingredient[];

}
Sign up to request clarification or add additional context in comments.

5 Comments

"subscribe" does not exists on type "Recipe[]".
Why are you going to subscribe the recipe type
I followed your example: "this.recipeService.getRecipes().subscribe(recipes => ..."
The correct instruction in "onInit" of the component is: this.recipeService.fetchData().subscribe(r => { this.recipes = r });
I have to explain that this is an exercise from a course and the tutor put the input/output variable "recipes" just because it started from fixed data. I won't put output data in service, too, in normale case, but i wanted to make it work as it is. With your example i have to make the variable as public, so i can syncronize when data comes to component. Nothing wrong for a mere exercise...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.