简体   繁体   中英

Angular NgRx - How to view object from the store in my template html?

Hey i have object in store and i want to view the object in the template.

My Ts File:

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Store } from '@ngrx/store';
import { Comment } from '../../models/comment.model';
import { User } from '../../models/user.model';
import { AppState } from '../../app.state';

@Component({
  selector: 'app-ngrx-get-data',
  templateUrl: './ngrx-get-data.component.html',
  styleUrls: ['./ngrx-get-data.component.scss']
})
export class NgrxGetDataComponent implements OnInit {
  comment$: Observable<Comment[]>;
  userDetails$: Observable<User>;

  constructor(private store: Store<AppState>) {
    this.comment$ = this.store.select('comment');
    this.userDetails$ = this.store.select('user');
  }

  ngOnInit() {
  }

}

My template:

<div style="margin: auto;">
<h1 style="text-align: center;">USER DETAILS FROM API</h1>
<li *ngFor="let item of userDetails$ | async ">
  <ul>{{item}}</ul>
</li>
</div>

My Error in console:

ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

I try this and its not work:

<h1 style="text-align: center;">USER DETAILS FROM API</h1>
<li *ngFor="let item of userDetails$ | keyvalue">
  <ul>{{item.key}} {{item.value}}</ul>
</li>

Image if my state: 在此处输入图片说明

What you need is to combine async and keyvalue pipes together. Also the order of the pipes important :

<h1 style="text-align: center;">USER DETAILS FROM API</h1>
<ul *ngFor="let item of userDetails$ | async | keyvalue">
  <li>{{item.key}}: {{item.value}}</li>
</ul>

Here's a demo stackblitz of this code: https://stackblitz.com/edit/angular-1rj8sc

This is the correct way to do it:

<div style="margin: auto;">
    <h1 style="text-align: center;">USER DETAILS FROM API</h1>
    <ul *ngIf="userDetails$ | async as details">
        <li *ngFor="let item of details">{{item}}</li>
    </ul>
</div>

First you need to let Angular subscribe to observable using async pipe, use that within an *ngIf otherwise it will try to iterate over something that does not exist yet. Next use *ngFor to create multiple <li> elements, not <ul>

If your slice of state 'user' is normalized and stored as an object with the key: object structure, you'll need to convert that to an array to iterate over it in the template.

You can easily convert it to an array with something like this

  private userDetails: User;
  constructor(private store: Store<AppState>) {
    this.comment$ = this.store.select('comment');
    // Use Object.values() to convert to an array with all the values of that object
    this.userDetails$ = this.store.select('user').subscribe(userDetails => {
     this.userDetails = Object.values(userDetails);
    });
  }

  // Then

  <li *ngFor="let item of userDetails">
    <ul>{{item}}</ul>
  </li>

Though it's hard to know exactly what's going on without seeing the data structure.

Some other notes: If userDetails is just a single object, and you want to iterate over each property, and get the key and value, use Object.entries()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM