3

I am getting an [object Object] while using Observable map in angular 2.

Here is the response object from the API service.

{
  "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
}

Here is the model I have created to map with the response.

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; 
}

Service class to call the http and map the response.

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 || { };
  }

Here is the Component.ts which is calling 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);});
}
}

When I see to the console I am getting [object Object] response. Where is the mistake I am not able to figure it out

San Jaisy
  • 15,327
  • 34
  • 171
  • 290
  • You are appending the objects to a string here- `console.log("Body Data = "+body.data);` ... Try this instead - `console.log("Body Data = ", body.data);` . And the same thing at `"this"+this.marketModel)` – P. Moloney Jan 13 '17 at 08:14

2 Answers2

4

You have a problem with your extractData, you want the response as it is, to match your MarketViewModel, so you need to remove the data from that method and also to return an empty object if there is no response:

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

Some pointers:

  • In your Service and MarketComponent you do not need to inject the MarketViewModel in your constructor.
  • You need to declare a variable marketModel in your component, to be able to use this.marketModel.
  • In component you have declared method ngOnInit, but not implemented it in your component

When testing your app it worked:

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

Your component:

marketmodel: MarketViewModel

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

Your view, you should wrap your html in an if-statement, since your data gets retrieved asynchronously:

e.g:

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

We need to remember though this code works wonderfully, we have not actually casted the response to be of instances of your classes. If you wish to do that, I suggest the following link with some great answers :) How do I cast a JSON object to a typescript class

AT82
  • 71,416
  • 24
  • 140
  • 167
3

You have to change your DashBoardService as below as you are have to return MarketListObject array as observable not 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 || [];
  }
}

Also there is no need to pass MarketViewModel as providers inside MarketComponent so remove MarketViewModel from MarketComponent providers list and change your component as below .

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);
    });
  }
}
ranakrunal9
  • 13,320
  • 3
  • 42
  • 43
  • It didn't work for me .. I am getting [object Object],[object Object],[object Object],[object Object] – San Jaisy Jan 13 '17 at 05:06
  • Inside `extractData` function or inside `ngOnInit` of `MarketComponent` ? also check by removing `:Observable` from `GetMarketListCall` functions return type. – ranakrunal9 Jan 13 '17 at 05:11
  • If I use subscribe in service then everything works fine. When I used map I am getting a object. Yeah I check in ngOnInit. I am still getting object – San Jaisy Jan 13 '17 at 05:19
  • i have updated component in my answer. inside component `marketList` variable should be array of `MarketListObject` like `public marketList: MarketListObject[]` so import it and change it if it required otherwise `any[]` will also work. – ranakrunal9 Jan 13 '17 at 05:26
  • Can you please let me know how to map with the class as the response from the web api class.I dont want direct array. I want to map with the object – San Jaisy Jan 13 '17 at 05:56
  • Try to check with `public GetMarketListCall() { return this.http.get(this.MarketUrl).map((res) => res.json()).catch(this.handleError); }` in service and `console.log(data)` inside subscribe code of `GetMarketListCall` API call inside your component – ranakrunal9 Jan 13 '17 at 05:58