0

I'm trying to use rxjs map to get an array of strings from a response. The response is an array of objects with guid and name property.

When i get the full response:

public getAllSolutions(): Observable<string[]> {
  return this.http.get(`${this.baseUrl}/Solution/All`)
    .map((results: Response) => results.json())
}

and output it using:

this.solutionsService.getAllSolutions().subscribe(
    data => {
      console.log(data);
    }
);

i get this:

[
{guid:"6e3d4646e1ad6d78bd225d2bdb5a14709c12e8280796a3b4f27536e8aaaf89ed", name: "Solution 1"},
{guid: "737f838cc457d833ff1dc01980aa56e9661304a26e33885defe995487e3306e7", name: "Solution 2"}
]

What i would like to have is an array just containing name

Following documentation this should work:

public getAllSolutions(): Observable<string[]> {
  return this.http.get(`${this.baseUrl}/Solution/All`)
    .map((results: Response) => results.json())
    .map(solutions => solutions.name);
}

but the output i get is undefined. What am i doing wrong here?

3
  • 8
    You should apply "map" on result array: .map(solutions => solutions.map(s => s.name)); Commented Feb 15, 2018 at 10:54
  • @AlekseyL. this is correct, thank you! I still don't really see what the first map applies to then? Isn't this first map already applied to the result array, as there is nothing else there? Or is the .json() result an object that contains an array? Commented Feb 15, 2018 at 12:00
  • Yeah, results.json() results in array (as you can see in console.log). So you could just apply Array.map in place, instead of doing it in second map on observable: .map((results: Response) => results.json().map(s => s.name)). I think it will be helpful to read about the difference between Array.map and Observable.map. Commented Feb 15, 2018 at 12:33

1 Answer 1

2

Let me give you a fully-corrected example because your return value isn't even defined properly for the values you are giving, even though it is what you are expecting. Here is a corrected version of your code:

/* This is your response example from your API (as per your comments) that is generated when you run the response.json() function in the Observable mapper:
 *
 * [
 *   {guid:"6e3d4646e1ad6d78bd225d2bdb5a14709c12e8280796a3b4f27536e8aaaf89ed", name: "Solution 1"},
 *   {guid: "737f838cc457d833ff1dc01980aa56e9661304a26e33885defe995487e3306e7", name: "Solution 2"}
 * ]
 */

// Define this interface outside of your class to make it easier to reason in your code, regardless of the function below that you choose. You can even put this interface into a different file, if you wish to do so.
interface Solution {
  guid: string;
  name: string;
}
 
// This should be the function, assuming RxJS (v4) and @angular HttpModule (v2-4):

public getAllSolutions(): Observable<string[]> {
  return this.http.get(`${this.baseUrl}/Solution/All`)
    .map((results: Response) => <Solution[]>results.json())
    .map((solutions: Solutions[]) => solutions.map((solution: Solution) => <string>solution.name));
}

// This should be the function, assuming RxJS (v5) and @angular HttpClientModule (v5+ currently):

// You need to import the map function from RxJS or else you will get all kinds of stupid errors that don't actually tell you that you need to include this function. This import is also case-sensitive. Fun times.
include { map } from 'rxjs/operators';

public getAllSolutions(): Observable<string[]> {
  return this.http.get(`${this.baseUrl}/Solution/All`)
    .pipe(
      map((response: Solution[]) => response.map((solution: Solution) => <string>solution.name))
    );
}
[
{guid:"6e3d4646e1ad6d78bd225d2bdb5a14709c12e8280796a3b4f27536e8aaaf89ed", name: "Solution 1"},
{guid: "737f838cc457d833ff1dc01980aa56e9661304a26e33885defe995487e3306e7", name: "Solution 2"}
]
What i would like to have is an array just containing name

Following documentation this should work:

public getAllSolutions(): Observable<string[]> {
  return this.http.get(`${this.baseUrl}/Solution/All`)
    .map((results: Response) => results.json())
    .map(solutions => solutions.name);
}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.