I'm creating a web app for a university project that comes in two parts: a Web API and a Frontend that connects to said API. The web app that I'm making is a recipe website. Having not touched new technologies such as Angular I took to the Tour of Heroes tutorial on their website and am coping fairly well with it.
However, I'm to the point now where I must link not use mock data sources and instead use my API to pull data from.
I have several components, and so I've included the relevant files for the HTTP section of the tutorial, recipe.service.ts and recipes.component.html, for this part of the app (the only files that should be edited in the tutorial.
It seems to me that Angular isn't reading the response as an array by the error code, although the supposed return text being JSON. I've looked this question up but couldn't seem to get the answers to work with my code correctly.
recipe.service.ts
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { Recipe } from './recipe';
import { RECIPES } from './mock-recipes';
import { MessageService } from './message.service';
import { HttpClient, HttpHeaders } from '@angular/common/http';
@Injectable()
export class RecipeService {
private recipesURL = 'http://localhost:3000/api/recipes';
constructor(
private http: HttpClient,
private messageService: MessageService) {}
getRecipes(): Observable<Recipe[]> {
//Todo: send the message after fetching heroes
//this.messageService.add('RecipeService: fetched recipes');
return this.http.get<Recipe[]>(this.recipesURL);
}
getRecipe(id: number): Observable<Recipe> {
this.messageService.add(`RecipeService: fetched recipe id=${id}`);
return of(RECIPES.find(recipe => recipe.recipeID === id));
//return of(RECIPES.find(recipe => recipe.recipeName));
}
private log(message: string) {
this.messageService.add('RecipeService: ' + message);
}
}
recipes.component.html
<h2>My Recipes</h2>
<ul class="recipes">
<li *ngFor="let recipe of recipes">
<a routerLink="/detail/{{recipe.recipeID}}">
<span class = "badge">{{recipe.recipeName}}</span> {{recipe.userID}}
</a>
</li>
</ul>
The error I'm getting in the console when running the Angular app:
ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
at NgForOf.ngOnChanges (common.js:2537)
at checkAndUpdateDirectiveInline (core.js:12092)
at checkAndUpdateNodeInline (core.js:13598)
at checkAndUpdateNode (core.js:13541)
at debugCheckAndUpdateNode (core.js:14413)
at debugCheckDirectivesFn (core.js:14354)
at Object.eval [as updateDirectives] (RecipesComponent.html:3)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:14339)
at checkAndUpdateView (core.js:13508)
at callViewAction (core.js:13858)
A snippet of what the application is supposed to pull back (as JSON):
{
"Error": false,
"Message": "Success",
"Recipes": [
{
"recipeID": 1,
"recipeName": "orci",
"ingredients": "Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl. Aenean lectus. Pellentesque eget nunc. Donec quis orci eget orci vehicula condimentum. Curabitur in libero ut massa volutpat convallis.",
"method": "Vivamus in felis eu sapien cursus vestibulum. Proin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem. Duis aliquam convallis nunc. Proin at turpis a pede posuere nonummy. Integer non velit.",
"createdBy": 150,
"postedTime": "2017-06-01 15:11:27"
},
{
"recipeID": 2,
"recipeName": "sit",
"ingredients": "Suspendisse potenti. In eleifend quam a odio.",
"method": "Donec semper sapien a libero. Nam dui. Proin leo odio, porttitor id, consequat in, consequat ut, nulla. Sed accumsan felis. Ut at dolor quis odio consequat varius. Integer ac leo.",
"createdBy": 982,
"postedTime": "2017-02-21 08:40:58"
}
]
}
If anyone could help me it would be great.
Thanks :)
EDIT - my recipes.component.ts
import { Component, OnInit } from '@angular/core';
import { Recipe } from '../recipe';
import { RecipeService } from '../recipe.service'
@Component({
selector: 'app-recipes',
templateUrl: './recipes.component.html',
styleUrls: ['./recipes.component.css']
})
export class RecipesComponent implements OnInit {
recipes: Recipe[];
constructor(private recipeService: RecipeService) { }
ngOnInit() {
this.getRecipes();
}
getRecipes(): void {
this.recipeService.getRecipes().subscribe(recipes => this.recipes = recipes);
}
}