Scott B
Scott B

Reputation: 40177

Angular Typescript access specific JSON object by id in an observable

I have this json string below and I want to either pull the "stocks" data array or the "contacts" data array based on whichever one I need for a given request:

[{
  "id": "stocks",
  "name": "Stocks",
  "data": [
    {
      "id": 1,
      "name": "Actuant Corporation",
      "symbol": "ATU"
    },
    {
      "id": 2,
      "name": "Xilinx, Inc.",
      "symbol": "XLNX"
    }
  ]
},
{
  "id": "contacts",
  "name": "Contacts",
  "data": [
    {
      "id": 1,
      "full_name": "Betty Traise"
    },
    {
      "id": 2,
      "full_name": "Hank Hurrion"
    },
    {
      "id": 3,
      "full_name": "Calvin Ommanney"
    }
  ]
}]

For example, in the function below, which is an observable, assume the payload argument is "contacts". In that case, I need to return the "id: "contacts" data array. Here's the code I'm using:

  loadData$(payload: any = {}): Observable<any> {
  // paths: {
  //   titlemaps: 'http://localhost:4100/data'
  // },
  // return this.service.get(this.config.paths.titlemaps, payload);
  const JSON: any  = this.service.get(this.config.paths.titlemaps, payload);
  console.log('payload: ' + payload, 'json: ' + JSON); // if payload is "contacts", return only the contacts
  return JSON.find(data => data.id === 'contacts');
}

The console log returns "contacts" and the entire JSON as expected. However, the JSON.find fails with error:

ERROR TypeError: JSON.find is not a function

When I switch the function types a bit, I get typescript compiler error:

[ts] Property 'find' does not exist on type 'Observable'.

What am I missing?

Upvotes: 0

Views: 1483

Answers (2)

Lazy Coder
Lazy Coder

Reputation: 1217

I moved the mapping/find operation to the service since you're passing those as params but you don't have to do it like that of course...

https://stackblitz.com/edit/angular-2lajx4

The gist...

  get(url, payload) {
    return of(results)
    .pipe(map((res: any) => {
      return res.find(data => data.id === payload)
    }));
  }

Just using of() here to simulate an observable, results is the JSON you provided above...

loadData$ subs to the get and puts the data into a variable for consumption

  data: any;

  loadData$(payload: any = {}) {
    this.service.get('../results.json', payload).subscribe(data => {
      this.data = data
      console.log('payload: ' + payload, 'json: ' + this.data); // if payload is "contacts", return only the contacts
    });
  }

Upvotes: 1

Jean-Marc Roy
Jean-Marc Roy

Reputation: 1791

The result of your service call seems to be an observable, you can transform the result and return a new value with rxjs pipeable operators:

import { map } from 'rxjs/operators';
....

loadData$(payload: any = {}): Observable<any> {
   return this.service.get(this.config.paths.titlemaps)
     .pipe(
        map(result => result.find(data => data.id === payload))
      );
}

Hope it helps!

Upvotes: 1

Related Questions