Chitova263
Chitova263

Reputation: 789

Map result from api to observables

I'm trying to map response from API as shown below using Rxjs

In service i have the following

export interface Response {
  data: Array<Data>;
  headers: Headers
}

public fetchData(): Observable<Response> {
   return http.get<Response>(myurl);
}

In my component I would like to map the response to the following observables

headers$: Observable<Headers>;
data$: Observable<Array<Data>>;

onInit(){
   myservice.fetchData()
     .pipe(
        //mapping response to the two observables here
     )
}

So that i would be able bind my data$ observable using async pipe in my template as follows

<div *ngIf="let item of data$ | async">
   {{ Whatever }}
</div>

Upvotes: 0

Views: 1936

Answers (3)

G&#233;r&#244;me Grignon
G&#233;r&#244;me Grignon

Reputation: 4228

You can manipulate a stream using rxjs operators but in your case, you need to intialize your observables with a given stream.

The quick solution would be to map each observable to the wanted infromation :

headers$: Observable<Headers>;
data$: Observable<Array<Data>>;

onInit(){
  this.headers$ = this.myService.fetchData().pipe(stream => stream.headers);
  this.data$ = this.myService.fetchData().pipe(stream => stream.data)

}

But it means you will make two http calls each time your component is rendered.

A better solution would be to use a Smart / Dump architecture coupled with the async pipe :

Parent component :

response$: Observable<Response>;

onInit(){
  this.response$ = this.myService.fetchData();

}

Parent template :

<ng-container *ngIf="response$ | async as response"
  <app-child [response]="response"></app-child>
</ng-container>

Child component :

@Input() response: Response

Child template :

<div *ngFor="let item of response.data">
   {{ Whatever }}
</div>

Upvotes: 3

Shravan
Shravan

Reputation: 1202

You can use the rxjs map operator to acheive what you need as shown below:

headers$: Observable<Headers>;
data$: Observable<Array<Data>>;

onInit(){
   const response = this.myservice.fetchData();
   this.headers$ = response.pipe(map(resp => resp.headers));
   this.data$ = response.pipe(map(resp => resp.data));
}

Now you can use the data$ and header$ observables along with async pipe in Template file to display the respective data.

Upvotes: 1

I think you are only interested in the observable, so I'd recommend you to suscribe to your fetchData method. And then you can map that response. For example:

myservice.fetchData().subscribe(
      (data)=>{
        //Map your response here  
      }
    )

Also another option, is that you can map in your fetchData method instead of doing it in the component.

Upvotes: 0

Related Questions