0

I am getting above error in

homes.component.html

when running Angular project to display list of homes from JSON file.

enter image description here

Json File

 [
    {
      "image_url": "https://images.unsplash.com/photo-1460317442991-0ec209397118?auto=format&fit=crop&w=500&q=80",
      "type": "Apartment",
      "location": "New York",
      "title": "Superb duplex apartment in the historical centre"
    },
    {
      "image_url": "https://images.unsplash.com/photo-1480074568708-e7b720bb3f09?auto=format&fit=crop&w=500&q=80",
      "type": "House",
      "location": "San Francisco",
      "title": "Charming house with woodstove"
    },
    {
      "image_url": "https://images.unsplash.com/photo-1522771739844-6a9f6d5f14af?auto=format&fit=crop&w=500&q=80",
      "type": "Room",
      "location": "New York",
      "title": "Nice Clean Room in Brownstone Studio"
    },
    {
      "image_url": "https://images.unsplash.com/photo-1522771739844-6a9f6d5f14af?auto=format&fit=crop&w=500&q=80",
      "type": "Room",
      "location": "San Francisco",
      "title": "Bright and Sunny Shared Room in Downtown"
    },
    {
      "image_url": "https://images.unsplash.com/photo-1480074568708-e7b720bb3f09?auto=format&fit=crop&w=500&q=80",
      "type": "House",
      "location": "Boston",
      "title": "Cape Cod Style House on South Shore"
    },
    {
      "image_url": "https://images.unsplash.com/photo-1522771739844-6a9f6d5f14af?auto=format&fit=crop&w=500&q=80",
      "type": "Room",
      "location": "San Francisco",
      "title": "Large Private Room Facing Golden Bridge"
    },
    {
      "image_url": "https://images.unsplash.com/photo-1480074568708-e7b720bb3f09?auto=format&fit=crop&w=500&q=80",
      "type": "House",
      "location": "New York",
      "title": "Single Family House in Quincy"
    },
    {
      "image_url": "https://images.unsplash.com/photo-1522771739844-6a9f6d5f14af?auto=format&fit=crop&w=500&q=80",
      "type": "Room",
      "location": "Boston",
      "title": "Small Clean Room near Boston University in Brookline"
    },
    {
      "image_url": "https://images.unsplash.com/photo-1480074568708-e7b720bb3f09?auto=format&fit=crop&w=500&q=80",
      "type": "House",
      "location": "San Francisco",
      "title": "Beach House near Restaurants"
    },
    {
      "image_url": "https://images.unsplash.com/photo-1460317442991-0ec209397118?auto=format&fit=crop&w=500&q=80",
      "type": "Apartment",
      "location": "New York",
      "title": "Rustic Apartment in Downtown"
    }
 ]

homes.component.html

<div class="uk-container uk-padding">
    <h1>Homes</h1>
    <div *ngFor="let home of homes$ | async">
        <div class="uk-card">
            <div class="uk-card-media-top">
                <img src="{{ home.image_url}}">
            </div>
            <div class="uk-card-body">
                <div>
                    {{ home.type}} / {{ home.location}}
                </div>
                <div>
                    {{ home.title}}
            </div>
        </div>
    </div>
</div>

data.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class DataService {

  constructor(private httpClient: HttpClient) { }

  getHomes() {
    return this.httpClient.get('assets/homes.json');
  }
}

homes.component.ts

import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';

@Component({
  selector: 'app-homes',
  templateUrl: './homes.component.html'
})
export class HomesComponent implements OnInit {

  homes$ = this.dataService.getHomes();

  constructor(private dataService: DataService) { }

  ngOnInit() {
  }

}

I am trying to display the list of homes from JSON file with image and some description under it.

sohaieb azaiez
  • 768
  • 9
  • 20
  • `homes$` return an Observable of an object not an iterable. – Matthieu Riegler Apr 22 '23 at 16:04
  • where and what should I change ? – Nilantha Samararathna Apr 22 '23 at 16:58
  • It should probably be an array. – Matthieu Riegler Apr 22 '23 at 17:29
  • How to define it ? any sample code ? – Nilantha Samararathna Apr 22 '23 at 17:43
  • Hey, you have to share your json file data content (not the *real* data but you can use an example structure that helps us to know how it is) , because your code looks good, but the returned value through the error message does not indicate that the http request is returung an iterable (array / array-like object). also, as a best practice, it would be better to execute the .getHomes() http request in the ngOnInit lifecycle instead of in the initialization phase of the HomeComponent fields – sohaieb azaiez Apr 23 '23 at 11:55
  • another remark: I'm not sure but, if your file is located in the assets as a static file of your same angular project, this case would be better to import the json file directly instead of making an http request (look at [this example](https://stackoverflow.com/a/48876138/8678900)). This would save you time and energy . – sohaieb azaiez Apr 23 '23 at 11:57
  • Json file added @sohaiebazaiez – Nilantha Samararathna Apr 23 '23 at 21:51

3 Answers3

0

In your assets/home.json, the data should be an array.

[
    {
        "image_url": "",
        "type": "",
        "location": "",
        "title": ""
    }
]
Praveen
  • 1
  • 2
  • yes it is an array – Nilantha Samararathna Apr 22 '23 at 20:30
  • Oh okay. As others have mentioned, move the initialisation of the $homes to either the constructor or the ngOnInit. The injected functions become available only after the component starts loading. So the code that you have written `homes$ = this.dataService.getHomes();` will set as `undefined`. Hence the error. – Praveen Apr 26 '23 at 14:13
0

Check if the property returned by the getHome method is an array. It might be interesting to place the assignment of homes$ within the ngOnInit lifecycle.

0

I used your code above to reproduce your work. Here is what I did to solve your problem:

  1. Be sure that your HttpClientModule and your DataServices are correctly imported and defined
  2. homes$ should be initialized in the ngOnInit() { ... } lifecyle, else it would not work because the subscription would not be executed in the view with the async pipe.
  3. I made a typescript definition file called json.d.ts to be able to import json files without performing http requests directly, and read it as an object (parse it) , and added both of the two configurations in tsconfig.json typescript file:
"compilerOptions": {
  ...
  "resolveJsonModule": true,
  "esModuleInterop": true
  ...
}
  1. Now, DataService file would be like this :
...
...
import data from './home.json';
import { of } from 'rxjs';
...
...
export class DataService {

  getHomes() {
    // if you need to work with http request , you should be sure that you can have
    // access to assets/homes.json through your server, so there is a configuration
    // to setup on your server
    //  return this.httpClient.get('assets/homes.json');
    return of(data);
  }
...
...
}

  1. Finally, in the Html view, I added a simple check with *ngIf:
 <ng-container *ngIf="homes$">
    <div *ngFor="let home of homes$ | async">
    </div>
 </ng-container>

PS: here is the full solution on StackBlitz, feel free to ask me if you find any thing wrong or any improvement.

sohaieb azaiez
  • 768
  • 9
  • 20