Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modify data in Observable in Angular 2?

I am working on learning Angular 2 and Typescript. I am building a simple web application that grabs data from a WEB API and displays it in a list. Then once the user clicks an item in the list, they are taken to a details page.

I have a service that I created to make the API call that does the following:

   GetData() { 
         let data = this.http.get('http://server.name/api/GetData')
                  .map((res) => res.json());
         return data; 
   }

Then in a component, I subscribe to the data like this:

      this.myService.GetData()
      .subscribe((myService) => this.items = myService);

When the http.get returns, I would like to do some processing on the JSON objects before I return from the GetData() method. For example, add a new property called ID. Essentially something like the pseudo code below:

 for each(item in data) { 
     item.ID = newID(); //method for creating IDs 
 }
  1. Is this something that can be done?
  2. If yes, is it something that SHOULD be done, or is there a better way to accomplish what I am trying to do?

Thanks

like image 495
user961714 Avatar asked Apr 20 '17 01:04

user961714


People also ask

How do I create a custom observable?

Steps to create custom observable in Angular First thing is to create an instance of Observable for which you can use Observable. create() method. This created observable instance defines a subscriber function. The subscriber function defines how to obtain or generate values to be published.

Can we convert observable into Promise?

How to Convert an Observable to a Promise in Angular? Since the get method of HttpClient returns an observable, we use the toPromise() method to convert the observable to a promise. Since you can convert an observable to a promise, you can make use of the async/await syntax in your Angular code.


2 Answers

You can do the processing in your GetData's code, within the map:

// For RxJS v5 
    this.http
      .get('http://server.name/api/GetData')
      .map(result => {
         const items = <any[]>result.json(); // could be SomeItem[] instead of any[]
         items.forEach(item => item.ID = ...);
         return items;
      });

// For RxJS v6 
    this.http
     .get('http://server.name/api/GetData')
     .pipe(map(result => {
        const items = <any[]>result.json(); // could be SomeItem[] instead of any[]
        items.forEach(item => item.ID = ...);
        return items;
      }));

Then when you receive the object in your subscribe, the items should have the IDs assigned.

Here's the reference to the RxJs Observable's documentation: http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-map

like image 190
Igor Soloydenko Avatar answered Oct 23 '22 00:10

Igor Soloydenko


the idea is to :

  • get the result
  • map the result to get the json only
  • as your json is an array, produce an Observable for each data, then change its id and sent the data back
  • gather them back in an array

the mergeMap (replaced flatMap in rxjs 5.5+) operator is used because an Observable operator always sends back an Observable, but since we create an Observable inside the result itself, it produces an Observable>, mergeMap removes an Observable layer. Hope this helps

GetData():Observable<WhateverWithIDInside[]> { 
  let data = this.http.get('http://server.name/api/GetData')
    .map(res => res.json())
    .mergeMap(dataArr =>
      Observable.from(dataArr)
        .map(data => {
          data.ID = newID();
          return data;
        })
        .toArray()
   );
}
like image 29
gropapa Avatar answered Oct 23 '22 00:10

gropapa