Búsqueda de sitios web

typescript - Obteniendo [object Object] al mapear la respuesta HTTP en Angular 2


Estoy obteniendo un [object Object] mientras uso map de Observable en Angular 2.

Aquí está el objeto de respuesta del servicio API.

{
  "isSuccess": true,
  "message": "Connection Successfull",
  "data": [
    {
      "marketId": 1,
      "city": "san",
      "cityF": "san",
      "name": null,
      "nameF": "hello",
      "sortOrder": 1,
      "isActive": true
    },
    {
      "marketId": 2,
      "city": "san",
      "cityF": "san",
      "name": null,
      "nameF": "hello",
      "sortOrder": 1,
      "isActive": true
    },
    {
      "marketId": 3,
      "city": "san",
      "cityF": "san",
      "name": null,
      "nameF": "hello",
      "sortOrder": 1,
      "isActive": true
    },
    {
      "marketId": 4,
      "city": "san",
      "cityF": "san",
      "name": null,
      "nameF": "hello",
      "sortOrder": 1,
      "isActive": true
    }
  ],
  "exceptionErrorMessage": null,
  "errorCode": 0,
  "successMessage": null
}

Aquí está el modelo que he creado para mapear con la respuesta.

export class MarketViewModel 
{
public isSuccess: boolean;
public message : string;
public successMessage : string;
public exceptionErrorMessage : string;
public errorCode: number;
public data: MarketListObject[];

}
export class MarketListObject 
{
    public marketId : number;
    public city: string;
    public cityF : string;
    public name : string;
    public nameF : string;
    public sortOrder : number;
    public isActive : boolean; 
}

Clase de servicio para llamar al http y mapear la respuesta.

import { Headers, RequestOptions } from '@angular/http';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { MarketViewModel} from "../ViewModel/Market.ViewModel";
import { Injectable }     from '@angular/core';
import { Http, Response } from '@angular/http';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class DashBoardService {
    private MarketUrl = "DashBoard/GetMarketList";
    private ResponseData: any;
    constructor(private http: Http, private router: Router, private  marketModel : MarketViewModel) {}

    public GetMarketListCall() :Observable<MarketViewModel> {
         return this.http.get(this.MarketUrl).map(this.extractData)
                    .catch(this.handleError);
    } 
private extractData(res: Response) {
    let body = res.json();
        console.log("Body Data = "+body.data);
    return body.data || { };
  }

Aquí está el Component.ts que está llamando a Service.ts

import { Component } from '@angular/core';
import { MarketViewModel} from "../ViewModel/Market.ViewModel";
import { DashBoardService} from "../Service/DashBoard.Service";
import { Observable } from 'rxjs/Observable';

 @Component({
     selector: 'Market-app',
    templateUrl: 'DashBoard/MarketListView',
    providers: [DashBoardService, MarketViewModel]
 })

export class MarketComponent {
  constructor(private DashBoardservice: DashBoardService, private  marketModel : MarketViewModel) {
   }

ngOnInit() {
        this.DashBoardservice.GetMarketListCall().subscribe(
                               data => {this.marketModel = data;
                                    console.log("this"+this.marketModel); }, 
                                err => {console.log(err);});
}
}

Cuando veo en la consola, estoy obteniendo una respuesta [object Object]. ¿Dónde está el error? No puedo averiguarlo.

Respuesta #1

Tienes un problema con tu extractData, quieres la respuesta tal como está, para que coincida con tu MarketViewModel, por lo que necesitas eliminar el data de ese método y también devolver un objeto vacío si no hay respuesta:

private extractData(res: Response) {
  let body = res.json();
  return body || {};
}

Algunos consejos:

  • En tu Service y MarketComponent no necesitas inyectar el MarketViewModel en tu constructor.
  • Necesitas declarar una variable marketModel en tu componente, para poder usar this.marketModel.
  • En el componente ha declarado el método ngOnInit, pero no lo ha implementado en su componente

Cuando probaste tu aplicación funcionó:

getMarketListCall(): Observable<MarketViewModel>{
    return this.http.get('theUrl')
        .map(res => res.json()) // or use the 'extractData'
        // .catch(this.handleError);
}

Tu componente:

marketmodel: MarketViewModel

ngOnInit() {
    this.DashBoarservice.GetMarketListCall()
       .subscribe(data => {
          this.marketModel = data;
        },
        err => { console.log(err); 
    });
}

En tu vista, deberías envolver tu HTML en una instrucción if, ya que tus datos se obtienen de manera asíncrona:

p.ej:

<div *ngIf="marketModel"> <!-- Here! -->
  <h2>MarketModel Message: {{marketModel.message}}</h2>
  <div *ngFor="let data of marketModel.data">Id: {{data.marketId}} </div>
</div><br>

Sin embargo, necesitamos recordar que aunque este código funciona maravillosamente, en realidad no hemos convertido la respuesta para que sea de instancias de tus clases. Si deseas hacer eso, sugiero el siguiente enlace con algunas excelentes respuestas :) ¿Cómo convierto un objeto JSON a una clase de TypeScript?

Respuesta #2

Tienes que cambiar tu DashBoardService como se indica a continuación, ya que tienes que devolver un arreglo de MarketListObject como observable, no MarketViewModel:

@Injectable()
export class DashBoardService {
  private MarketUrl = "DashBoard/GetMarketList";
  private ResponseData: any;

  constructor(private http: Http, private router: Router, private  marketModel : MarketViewModel) {}

  public GetMarketListCall() :Observable<MarketListObject[]> {
     return this.http.get(this.MarketUrl).map(this.extractData)
                .catch(this.handleError);
  } 

  private extractData(res: Response) {
    let body = res.json();
    console.log("Body Data = "+body.data);
    return body.data || [];
  }
}

Además, no es necesario pasar MarketViewModel como proveedores dentro de MarketComponent, así que elimina MarketViewModel de la lista de proveedores de MarketComponent y cambia tu componente como se indica a continuación.

import { Component } from '@angular/core';
import { DashBoardService} from "../Service/DashBoard.Service";
import { Observable } from 'rxjs/Observable';

@Component({
  selector: 'Market-app',
  templateUrl: 'DashBoard/MarketListView',
  providers: [DashBoardService]
})
export class MarketComponent {

  public marketList: any[];

  constructor(private dashBoardservice: DashBoardService) {
  }

  ngOnInit() {
    this.dashBoardservice.GetMarketListCall().subscribe((data) => { 
      this.marketList = data;
      console.log("this" + this.marketList);
    },(err) => {
      console.log(err);
    });
  }
}

Artículos relacionados