deviloper
deviloper

Reputation: 7240

Angular datatable results: Error trying to diff '[object Object]'. Only arrays and iterables are allowed

I have a simple query to get some orders from an API using httpClient post method in Angular 5.

I get the proper response but I cant figure it out how to show them in the datatable.

Below is what I have tried:

order.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Order } from '../models/order.model';

@Injectable()
export class OrderService {

  constructor(private http: HttpClient){
    console.log('OrderService Initialized...');
  }

  getOrders(): Observable<Order[]>{
    var url = 'http://example.com/api/orders?type=1';
    var headers = new HttpHeaders().set('x-mobile-token', 'xxxxx');
    return this.http.get<Order[]>(url, {headers: headers});
  }
}

orders.component.ts

import { Component, OnInit } from '@angular/core';
import { OrderService } from '../../services/order.service';
import { Observable } from 'rxjs/Observable';
import { DataSource } from '@angular/cdk/collections';
import { User } from '../../models/order.model';

@Component({
  selector: 'orders',
  templateUrl: './orders.component.html',
  styleUrls: ['./orders.component.css'],
  providers: [OrderService]
})

export class OrdersComponent implements OnInit{

  constructor(private _orderService: OrderService, private router: Router, private cookieService: CookieService) {
    console.log('Orders Component Initialized...');
  }

  dataSource = new OrderDataScource(this._orderService);
  displayedColumns = ['id', 'courier', 'price', 'status', 'createdat'];
}

export class OrderDataScource extends DataSource<any> {
  constructor(private _orderService: OrderService){
    super();
  }

  connect(): Observable<Order[]>{
    return this._orderService.getOrders();
  }

  disconnect(){}
}

order.model.ts

export interface Order{
  id: number;
  courier: {
    name: string;
  },
  price: number;
  status: string;
  createdat: string;
}

orders.component.html

<div class="col-md-12">


<mat-table [dataSource]="dataSource">
    <ng-container matColumnDef="id">
      <mat-header-cell *matHeaderCellDef>آیدی</mat-header-cell>
      <mat-cell *matCellDef="let order">{{order.id}}</mat-cell>
    </ng-container>
    <ng-container matColumnDef="courier">
      <mat-header-cell *matHeaderCellDef>نام پیک</mat-header-cell>
      <mat-cell *matCellDef="let order">{{order.courier.name}}</mat-cell>
    </ng-container>
    <ng-container matColumnDef="price">
      <mat-header-cell *matHeaderCellDef>قیمت</mat-header-cell>
      <mat-cell *matCellDef="let order">{{order.price}}</mat-cell>
    </ng-container>
    <ng-container matColumnDef="createdat">
      <mat-header-cell *matHeaderCellDef>زمان ثبت</mat-header-cell>
      <mat-cell *matCellDef="let order">{{order.createdat}}</mat-cell>
    </ng-container>
    <ng-container matColumnDef="status">
      <mat-header-cell *matHeaderCellDef>وضعیت</mat-header-cell>
      <mat-cell *matCellDef="let order">{{order.status}}</mat-cell>
    </ng-container>
    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
  </mat-table>
</div>

What i get is only the header of the table in the browser and the following:

ERROR Error: Error trying to diff '[object Object]'. Only arrays and iterables are allowed

in console.

The following response is what I get via postman:

{
  "data": {
    "orders": [
      {
        "id": 1460,
        "customer_id": 98,
        "customer": {
          "id": 98,
        },
        "courier": {
          "user_id": 776,
          "fullname": "محمدحسن زارع",
          "rate_average": 5,
          "has_box": 0,
        },
        "invoice": {
          "price": 2500,
          "final_price": 2500,
          "payment_type": "credit"
        },
        "progress": 0,
        "transport_type": "motorbike",
        "updated_at": "5 ساعت و 14 دقيقه قبل",
        "created_at": "5 ساعت و 15 دقيقه قبل",
        "status": {
          "last_status": "delivering",
          "created_at": "5 ساعت و 14 دقيقه قبل"
        }
      }
    ]
  }
}

Upvotes: 1

Views: 3505

Answers (1)

Eliseo
Eliseo

Reputation: 57939

when you make http.get you received an Object, NOT an array. You must return the array orders that is a property of your object data

getOrders(): Observable<Order[]>{
    var url = 'http://example.com/api/orders?type=1';
    var headers = new HttpHeaders().set('x-mobile-token', 'xxxxx');
    return this.http.get<Order[]>(url, {headers: headers})
    .map(response=>response.data.orders); //Not return the response,
                          // just the property data.orders
  }

Upvotes: 5

Related Questions