Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON data loaded from http.get() is undefined in my Angular 2 template

I'm trying to read a local json file and parse it into a class that i made which have the same properties. When i try to read from the class, it gives me errors saying the class is null or undefined.

I have a file hall.ts which looks like this:

import {Item} from '../item/item';
export class Hall {
    constructor(public id:number,
                public naam:string,
                public oppervlakte:number,
                public aantalItems:number,
                public itemsMetNodigeActie:number,
                public items:Item[]) {
    }
}

It uses item.ts:

export class Item {
    constructor(public categorie:string,
                public naam:string,
                public productnummer:string,
                public omschrijving:string,
                public laatsteUitgevoerdeActie:Actie,
                public eerstVolgendeActie:Actie) {
    }
}
export class Actie{
    constructor(datum: string,
                type: string,
                omschrijving: string){}
}

The json file, hall1.json, that i'm trying to read from looks like this:

{
  "id": 1,
  "naam": "hall1",
  "oppervlakte": 100,
  "aantalItems": 3,
  "itemsMetNodigeActie": 3,
  "items": [
    {
      "id": 1,
      "categorie": "machine",
      "productnummer": "ADE124e",
      "omschrijving": "print papieren af",
      "laatsteUitgevoerdeActie": {
        "datum": "2015-01-05T00:00:00.000Z",
        "type": "vervanging",
        "omschrijving": "papier vervangen"
      },
      "eerstVolgendeActie": {
        "datum": "2016-01-06T00:00:00.000Z",
        "type": "vervanging",
        "omschrijving": "inkt vervangen"
      }
    }
  ]
}

I'm using a hall.service.ts which tries to read the json file which is locally stored, and returns it in an Hall object. This is the methode for doing that:

public getHall(): Observable<Hall> {
    return this.http.get('app/hall/hall1.json')
        .map((res:Response) => res.json());
}

I use this method in my hallDetail.component.ts

export class HallDetailComponent implements OnInit{
    public hall: Hall;
    constructor(
        private service: HallService
    ){}
    ngOnInit(){
        this.service.getHall().subscribe((hall:Hall) => {
            this.hall = hall;
        })
    }
}

So far it doesn't give me any errors, but when i try to read from the hall object, it sais that it is undefined

@Component({
    template: `
  <div>
    {{hall.naam}}
  </div>
  `
})

Error :

EXCEPTION: TypeError: Cannot read property 'naam' of undefined in [
    {{hall.naam}}
   in HallDetailComponent@1:7]
like image 914
Kupi Avatar asked Dec 31 '15 13:12

Kupi


People also ask

How to access your JSON file locally in Angular 2+?

In order to access your file locally in Angular 2+ you should do the following (4 steps): [1] Inside your assets folder create a .json file, example: data.json [2] Go to your angular.cli.json (angular.json in Angular 6+) inside your project and inside the assets array put another object (after the package.json object) like this:

How do I get data from an API in angular?

There are several ways to interact or get data from an API which includes using the infamous XMLHttpRequest request object or using the newer shiny version called the Fetch API. Fortunately, Angular ships with an HTTPClient module which provides a wrapper around XMLHttpRequest for us.

How do I create a website using Angular 2?

Create a new website. Provide the name and the location of the website. Click "Next". After adding all mandatory Angular 2 files, add a new TypeScript file. } // This is just a sample script. Paste your real code (javascript or HTML) here. Now, add a demo JSON file and add some data.

What is GET () method in angular http?

get () is the method of angular Http API that interacts with server using HTTP GET method. It accepts a HTTP URL and returns Observable instance. RequestOptionsArgs is optional.


1 Answers

You have to remember that the http.get() call is async. Your template is trying to process hall as an object before it has been resolved by your async http call.

That's why hall is undefined and, therefore, you can't access any properties on it (it does not yet exist).

As Eric mentioned in the comment, try something like this for your template:

@Component({
    template: `
  <div>
    {{hall?.naam}}  <!-- note the added ? -->
  </div>
  `
})

That will make the reference to naam on hall null safe.

Update:

For the sake of completeness, I'll point out that you can actually use *ngIf for this as well, though the null safe check makes for a cleaner looking template.

@Component({
    template: `
  <div *ngIf="hall"> <!-- note the added *ngIf -->
    {{hall.naam}}
  </div>
  `
})
like image 117
Michael Oryl Avatar answered Sep 22 '22 19:09

Michael Oryl