2
votes

I'm new in Angular and I have an error need to fix. This is the error I've encountered when I'm trying to display a list of data from jsonplaceholder. I don't know what is wrong in the code. May I ask for a help guys? Thank you.

ERROR TypeError: Cannot read property '0' of undefined at RecipeService.push../src/app/recipes/recipe.service.ts.RecipeService.getRecipe (recipe.service.ts:25) at SafeSubscriber._next (recipe-detail.component.ts:26) at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:196) at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next (Subscriber.js:134) at Subscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._next (Subscriber.js:77) at Subscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (Subscriber.js:54) at BehaviorSubject.push../node_modules/rxjs/_esm5/internal/BehaviorSubject.js.BehaviorSubject._subscribe (BehaviorSubject.js:22) at BehaviorSubject.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable._trySubscribe (Observable.js:43) at BehaviorSubject.push../node_modules/rxjs/_esm5/internal/Subject.js.Subject._trySubscribe (Subject.js:89) at BehaviorSubject.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe (Observable.js:29)

recipe-detail.component.ts

  ngOnInit() {
    this.route.params
      .subscribe(
        (params: Params) => {
          this.id = +params['id'];
          this.recipe = this.recipeService.getRecipe(this.id);
        }
      );
  }

recipe.service.ts

@Injectable()
export class RecipeService {
  recipesChanged = new Subject<Recipe[]>();

  private url = "https://jsonplaceholder.typicode.com/users/";

  private recipes: Recipe[];

  constructor(private slService: ShoppingListService, private http: Http) {}

  getRecipes() {
    return this.http.get(this.url).pipe(map(res => res.json()));
  }

  getRecipe(index: number) {
    return this.recipes[index];
  }

recipe-detail.component.html

<div class="row">
  <div class="col-xs-12" *ngFor="let recipe of recipes">
    <h1 class="list-group-item-heading">{{ recipe.id }}</h1>
    <h4 class="list-group-item-heading">{{ recipe.name }}</h4>
    <h4 class="list-group-item-heading">{{ recipe.username }}</h4>
    <h4 class="list-group-item-heading">{{ recipe.email }}</h4>
    <h4 class="list-group-item-heading">{{ recipe.phone }}</h4>
  </div>
</div>
3
What version of Angular are you using?dream88
@dream88 - I'm currently using Angular 7Gavz
And when do you call getRecipes() ?SeleM
Maybe not relate to your issue, but you should consider changing Http in constructor(private slService: ShoppingListService, private http: Http) {} to HttpClient: read about it heredream88
@selemmn - getting the data from jsonplaceholder but the error is in getRecipe methodGavz

3 Answers

0
votes

It could be that the recipes are null/undefined. So when you call getRecipe(0) this error comes up.. Try changing your method to something like this:

getRecipe(index: number) {
    if (!!this.recipes && this.recipes.length > index) {
       return this.recipes[index];
    } else {
       return 0; //Whatever
    }
}
0
votes

In the component you pass in the id to the getRecipe() method of the service. But, you cannot be sure it exists which is why it is occurring. Also, where, in the service, does 'recipes' come from? You initialize it, but never assign it any value (especially as an array). I.e., you aren't calling getRecipes() at all.

So alter the service:

getRecipe(index: number) {
  return this.recipes[index] ? this.recipes[index] : null;
}

So now in your component this.recipe may equal 'null' but you won't get the error.

0
votes

private recipes: Recipe[] is not initialized here. You must have check for undefined and length before accessing the element.

Component

getRecipe(index: number) {
    if(this.recipes && this.recipes.length > index){
        return this.recipes[index];
    }else{
       return null;
    }

}

RecipeService

@Injectable()
export class RecipeService {
  recipesChanged = new Subject<Recipe[]>();

  private url = "https://jsonplaceholder.typicode.com/users/";

  private recipes: Recipe[];

  constructor(private slService: ShoppingListService, private http: Http) {
      this.getRecipes().subscribe(recipes=>this.recipes); //<-- you may call from somewhere else.
  }

  getRecipes() {
    return this.http.get(this.url).pipe(map(res => res.json()));
  }

  getRecipe(index: number) {
    return this.recipes[index];
  }