简体   繁体   中英

Problem iterating through JSON in Angular

In an Angular project I am working in I am trying to iterate through some JSON located in my project. The Angular project compiles but I keep getting the dreaded:

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

As I understand it, you cannot iterate an Object of JSON (???) -- you have to somehow turn it into an Array or some "iterable" container/structure etc. in order to get the * ngFor to work. I have tried about everything on stack overflow -- I am missing the bit to change that object to an Array so the *ngFor in my newemployee.component.html works correctly:

<tr *ngFor="let employee of emplist">

This is my service typescript code (employee.service.ts):

import { Injectable } from '@angular/core';
import { Employee2 } from '../employee2';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';
import { MessageService } from '../message.service';

@Injectable({
  providedIn: 'root',
})
export class EmployeeService {
  url: string;

  constructor(
    private http: HttpClient,
    private messageService: MessageService
  ) {
    this.url = `/assets/json/employees.json`;
  }

  //gets the Employees from the file:
  getEmployees(): Observable<Employee2[]> {
    return this.http //.get(this.url)
      .get<Employee2[]>(this.url)
      .pipe(catchError(this.handleError<Employee2[]>('getEmployees', [])));
  }

  private handleError<T>(operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {
      console.error(error); // log to console instead

      this.log(`${operation} failed: ${error.message}`);

      // Let the app keep running by returning an empty result.
      return of(result as T);
    };
  }

  private log(message: string) {
    this.messageService.add(`EmployeeService: ${message}`);
  }
}

This is my newemployee.component.ts:

import { Component, OnInit } from '@angular/core';
import { Employee2 } from '../employee2';
import { EmployeeService } from '../services/employee.service';

@Component({
  selector: 'app-newemployee',
  templateUrl: './newemployee.component.html',
  styleUrls: ['./newemployee.component.css'],
})

export class NewemployeeComponent implements OnInit {
  emplist: Employee2[];

  // Inject the service into newemployees.component.ts file via a constructor.
  constructor(private employeeService: EmployeeService) {}
  ngOnInit(): void {

    this.employeeService.getEmployees().subscribe((data) => {
      this.emplist = data;
    });
  }
}

And this is newemployee.component.html:

<br>
<div class="col">

<h2>Department Store Employees</h2>
        <table class="table table-bordered table-striped">
          <thead class="thead-dark">
      <tr>
        <th scope="col">ID</th>
        <th scope="col">Name</th>
        <th scope="col">Salary</th>
        <th scope="col">Age</th>
      </tr>
  </thead>
  <tbody>
    <tr *ngFor="let employee of emplist">
        <td scope="row">{{employee.id}}</td>
        <td>{{employee.employee_name}} </td>
        <td>{{employee.employee_salary}}</td>
        <td>{{employee.employee_age}} </td>     
    </tr>
</tbody>
</table>
</div>

Also this is the interface for Employee2:

export interface Employee2{

    id: number;
    employee_name: string;
    employee_salary: number;
    employee_age: number;
    profile_image: string; //path to image.
}

Finally the JSON file employees:

{
    "status": "success",
    "data": [{
        "id": 1,
        "employee_name": "John Public",
        "employee_salary": 320800,
        "employee_age": 61,
        "profile_image": ""
    }, {
        "id": 2,
        "employee_name": "John Summers",
        "employee_salary": 170750,
        "employee_age": 63,
        "profile_image": ""
    }, {
        "id": 3,
        "employee_name": "James Cox",
        "employee_salary": 86000,
        "employee_age": 66,
        "profile_image": ""
    },{
        "id": 24,
        "employee_name": "Chuck Wilder",
        "employee_salary": 85600,
        "employee_age": 23,
        "profile_image": ""
    }],
    "message": "Successfully! All records has been fetched."
}

Ideally this is what it should look like

The JSON you're retrieving from the service doesn't return an array but an object, on your component you should do this:

this.employeeService.getEmployees().subscribe((data) => {
  this.emplist = data.data;
});

Since your service is returning an object, your *ngFor directive can't iterate through it.

Try with this changes. The problem is that You are converting the JSON to type which is not with the same structure.

extract interface Response {
    status: string;
    data: Employee2[];
}

getEmployees(): Observable<Response> {
    return this.http //.get(this.url)
      .get<Response>(this.url)
      .pipe(catchError(this.handleError<Response>('getEmployees', {})));
}

export class NewemployeeComponent implements OnInit {
  emplist: Employee2[];

  // Inject the service into newemployees.component.ts file via a constructor.
  constructor(private employeeService: EmployeeService) {}
  ngOnInit(): void {

    this.employeeService.getEmployees().subscribe((response) => {
      this.emplist = response.data;
    });
  }
}

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