3

I have an object in our server that is like this;

{
    "NBA": {
        "link": "https://www.nba.com/",
        "ticketPrice": 50
    },
    "UEFA": {
        "link": "https://www.uefa.com/",
        "ticketPrice": 39
    },
    "CL": {
        "link": "https://www.uefa.com/uefachampionsleague/",
        "ticketPrice": 76
    },
    "EuroLeague": {
        "link": "https://www.euroleague.net/",
        "ticketPrice": 42
    }
}

I subscribe this object with this piece of code;

sportsObject : Sports[] //THIS IS THE MEMBER THAT SHOULD BE FILLED WITH THE JSON OBJECT GIVEN
object = Object;
ngOnInit(){
    this.SportsService.getPrices().subscribe(data=>{
      this.sportsObject = data;
    })    
}

And here is my html code;

   <div *ngFor="let key of Object.keys(sportsObject)">
       <p>The {{key}} is {{{{sportsObject[key]}}</p>
   </div>

But I get the "Cannot find a differ supporting object '[object Object]' of type 'object'." error. How can I properly iterate this JSON object?

3
  • *ngFor only accepts arrays. You need to convert your object to iterable array. Commented Aug 20, 2020 at 13:32
  • @Kirubel how can I do that? Commented Aug 20, 2020 at 13:34
  • The json should be { "sports": [ "NBA": {...}, "UEFA": {...} ... ] } so that the service actually returns an array. Commented Aug 20, 2020 at 13:37

3 Answers 3

3

*ngFor directive by default supports iterables like arrays. Here you could try to use the keyvalue pipe (Angular v6.1.0+) to iterate over objects. Try the following

<div *ngFor="let sport of sportsObject | keyvalue">
  <p>The {{ sport.key }} is {{ sport.value.ticketPrice }}</p>
  <p>More Info: <a [attr.href]="sport.value.link">{{ sport.value.link }}</a></p>
</div>

Also as a sidenote, it's generally better to avoid calling functions in directive bindings ([dir]="someFunc()" and *dir="someFunc()") and interpolations ({{ someFunc() }}). The reason is if you aren't controlling the change detection strategy, then the functions would be triggered for each CD cycle and might lead to performance issues.

Sign up to request clarification or add additional context in comments.

Comments

0

In your ts file hold keys as an array

this.sportsObject = data;
this.keys= Object.keys(data);

And in your template directly use this array

<div *ngFor="let key of keys">
    <p>Key is: {{ key }}</p>
    <p>{{ sportsObject[key].link }}</p>
    <p>{{ sportsObject[key].ticketPrice }}</p>
</div>

Comments

0

You can use keyvalue pipe. Also, I'd recommend to use async pipe instead of assigning data from the API to sportsObject. It could look like that:

TS:

sports$: Observable<Sports>;    

ngOnInit(){
  this.sports$ = this.SportsService.getPrices();
}

HTML:

<div *ngFor="let sport of (sports$ | async) | keyvalue">
   <p>The {{sport.key}} is {{sport.value}}</p>
</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.