Search code examples
angularrestangular-httpclient

Angular 7 HttpClient Get Request undefined response


GET Request from API undefined error

Data is displayed but console show undefined error at line 46: ERROR TypeError: Cannot read property 'detaljne' of undefined and ERROR Context PostComponent.html:46

JSON is nested in JSON-Server

TS

import { Component, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { Post } from "../post.model";
import { ServerService } from "../server.service";

@Component({
  selector: "post",
  templateUrl: "./post.component.html",
  styleUrls: ["./post.component.css"]
})
export class PostComponent implements OnInit {
  post: Post[];

  constructor(
    private route: ActivatedRoute,
    private serverService: ServerService
  ) {}

  ngOnInit(): void {
    this.getPost();
  }

  getPost(): void {
    const id = +this.route.snapshot.paramMap.get("id");
    this.serverService.getPosts(id).subscribe(post => (this.post = post));
  }
}

HTML

<div *ngFor="let detaljne of post.detaljne" class="row-info">
   <p>{{ detaljne.name }}</p>
   <p>{{ detaljne.value }}</p>
</div>

post.model.ts

import { Detaljne } from "./detaljne.model";
import { Deserializable } from "./deserializable.model";

export class Post implements Deserializable {
  public id: number;
  public detaljne: Detaljne[];

  deserialize(input: any): this {
    Object.assign(this, input);
    this.detaljne = input.detaljne.map(detaljne =>
      new Detaljne().deserialize(detaljne)
    );
    return this;
  }
}

JSON

{
      "id": 1,
      "detaljne": [
        {
          "name": "Marka",
          "value": "Audi"
        },
        {
          "name": "Model",
          "value": "A6"
        }
      ]
    },

Solution

  • You are trying to access a property of post in your *ngFor, but you don't check whether post itself exists yet. To fix this you can use *ngIf

    Using *ngIf="post" won't render the HTML element until post is defined.

    <ng-container *ngIf="post">
      <div *ngFor="let detaljne of post.detaljne" class="row-info">
          <p>{{ detaljne.name }}</p>
          <p>{{ detaljne.value }}</p>
      </div>
    </ng-container>
    

    Note: You can't use *ngFor and *ngIf on the same element, so you use <ng-container> which is just a 'wrapper' that wont create an actual element on the DOM.

    Alternatively there's the safe navigation operator ?, which is slightly different as it's like doing post!== null ? product.detaljne: null. Both options are valid, just pick the one that suits best :)