1
votes

I have a device that contains several items. Now I want to display all items of the device in my Angular App on the HTML page, but I have problems iterating the observable that contains the array. I get the following error with my current code.

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

<tbody *ngFor="let item of (device | async).itemMap">
  <tr>
    <td>{{ item.name }}</td>
    // ...
  </tr>
</tbody>
export interface Device {
  items: DeviceItem[];
}

@Input()
public device: Observable<Device>;
3

3 Answers

2
votes

If your observable emits a Device model as you described (and NOT an array of Device) :

export interface Device {
  items: DeviceItem[];
}

public device$: Observable<Device>;

In the code above, I recommend you to use the convention device$ (a $ symbol as a suffix to differenciate Observable and regular type).

your template code should be :

  <tr *ngFor="let item of (device$ | async).items">
    <td>{{ item.name }}</td>
    // ...
  </tr>

or

  <ng-container *ngIf="device$ | async as device">
    <table>
      <tr *ngFor="let item of device.items">
        <td>{{ item.name }}</td>
        ...
      </tr>
    </table>
  </ng-container>

0
votes

Well *ngFor iterates only over a collection.So what you have to do to create a subject which contains your device type array and fill the data over it.

public device : Subject<Device[]> = new Subject();

and then fill this device with data like this -

this.device.next(data);
0
votes

Map device to items in ts file (you will need to update it manually if input is changed):

export interface Device {
  items: DeviceItem[];
}

@Input()
public device: Observable<Device>;
public items$ = device.pipe(map(x => x.items));

And then use it as normal:

<tr *ngFor="let item of items$">
<td>{{ item.name }}</td>
// ...