angular: HttpClient map response

Viewed 94082

Currently I'm switching from http (@angular/http) to HttpClient (@angular/common/http) and have problems mapping my response to objects.

Old code (was working before)

this.http.get(environment.baseUrl + '/api/timeslots')
            .map((response: Response) => {
                    const data = response.json();
                    const timeslots = Array.of<Timeslot>();
                    for (const item of data) {...}

New code, but compilation error:

this.httpClient.get(environment.baseUrl + '/api/timeslots')
                .map((response: Response) => {
                        const data = <Timeslot[]> response;
const timeslots = Array.of<Timeslot>();
                    for (const item of data) {...}

Do I miss a cast? The response is an array of Timeslots.

4 Answers

Default value that returns new HttpClient is Object. It automatically calls response.json() internally.

You can tell HttpClient what type the response will be, so:

this.httpClient.get<Timeslot[]>(...)
 .map((timeSlots) => {
   ...

where timeSlots's type will be Timeslot[]

See more information about typecheking in new HttpClient

Since Angular 6/7 there have been a couple of modifications to the implementation of the RxJS library within Angular.

Hence, the RxJS operators are now located at 'rxjs/operators' instead of 'rxjs/add/operator/:OperatorName'. Also, these operators can no longer be directly chained to the observebale, instead they have to be chained through the pipe() method.

So, the new way of implementing this must look like this:

import {map} from 'rxjs/operators';

this.http.get(...)
  .pipe(
    map( response => {
     // TODO: Do Your Staff Here! 
   } )
  );

Please, refer to the specific Angular's documentation here for more details. * Here I'm assuming that your HttpClient component is available under this.http prop.

You still can, but you need to import the map()-operator from rxjs like this:

import 'rxjs/add/operator/map';

And you will have the map() operator.

(See also my answer here: https://stackoverflow.com/a/48323851/348841)

I will leave here the code that works for me to map response to what I need.

I have a dummy response that looks like this.

[
    {
        "helloId": 52,
        "hello1": "NiceTag",
        "hello2": "time",
        "tag": {
            "type": "NICE_HELLO",
            "name": "9f7938bd-3d98-4531-a5df-1c503aed6a74"
        }
    }
]

Here is the way I map it to an object

 getHello(id: string) {
    return this.http.get<any>(`http://localhost:8080/hello/${id}`)
      .pipe(map(response => ({
          hello: response[0].hello1
      })));
  }

Note the following things:

  • My response is a list, so I needed to map values of the first element -response[0]
  • To be able to refer to the fields directly (meaning the way they are written in the response) like response[0].hello1 you need to add <any> after get. Otherwise you will get an Error sth like Property 'hello1' does not exist on type 'Object'
  • In my example there is no subscribe cause I am using it later in another function, but it can look sth like this, where I already refer to the value of the field by the name I gave it to while mapping.
.subscribe(data => {
      this.getResponse = data.hello;
})

And yes you of course need to import map like so import {map} from "rxjs";

I use Angular 13, btw

Related