5

In my Angular application I use HttpClient to get json data from server. However, I need to do some conversion to the returned data at the client-side.

So I try to convert an array of Type A returned from the server to an array of Type B with the following code snippet.

this.http.get<any[]>(this.env.accounts.url.accountTypes).pipe(map(e => {
    console.log(e); // print the retuned array not a single item
    return {'label': e.name, 'value': e.id}
  }
)).subscribe(data => {
  this.accountTypes = data;
  console.log(this.accountTypes); // prints {label: undefined, value: undefined}
});

I must be doing this wrong, but I cannot figure out what is wrong here.

The server returns an array like:

[
  {name: "Name 1", id: 1},
  {name: "Name 2", id: 2},
  {name: "Name 3", id: 3},
]

And I need to convert it into the following format

[
  {label: "Name 1", value: 1},
  {label: "Name 2", value: 2},
  {label: "Name 3", value: 3},
]

Can somebody please point out what is wrong in my code and how to fix it.

3
  • As you correctly noticed e is an Array and not a single item. With e.name and e.id you are trying to return name and id of the array! You need to map the content of the array too. Commented Jul 26, 2019 at 7:05
  • @NicholasK, of course, I know AnguarJs is predecessor o Angular and have a number of differences. But I don't understand what tags you want me to add here. Commented Jul 26, 2019 at 8:39
  • @NicholasK, you are right. I had entered angularjs instead of angular, he has corrected it. Commented Jul 26, 2019 at 8:45

4 Answers 4

9

You are confusing Array.map, with RxJS's map operator.

As stated on the RxJS documentation for the map operator, the purpose of Map is to

Apply projection with each value from source.

What you can do instead, is this:

this.http.get<any[]>(this.env.accounts.url.accountTypes)
  .pipe(
    map(res => {
      // insert logic 
      const data = res.map(obj => ({
        label: obj.name,
        value: obj.id
      }));
      return data;
    })
  )).subscribe(data => {
    this.accountTypes = data;
    console.log(this.accountTypes); // prints {label: undefined, value: undefined}
  });
Sign up to request clarification or add additional context in comments.

Comments

4

As mentioned in the comment please also map the array content

return e.map(entry => {'label': entry.name, 'value': entry.id});

Comments

2

You can transform the data using the map operator:

var result = [];
x.map(e => {
  const obj = {};
  obj['label'] = e.name;
  obj['value'] = e.id;
  result.push(obj);
})

Comments

0

Of course there are many solutions but Model Adapter can be a generic solution.

// app/core/adapter.ts
export interface Adapter<T> {
    adapt(item: any): T;
}
export class AccountType {
//.....
}
export class AccountAdapter implements Adapter<AccountType> {

    adapt(item: any): AccountType {
        return new AccountType(
            item.id,
          --  item.name,
          ++  item.value,
        );
    }
}


export class AccountService {
    private baseUrl = 'http://api.*';
    constructor(
        private http: HttpClient,
        private adapter: AccountAdapter,
    ) { }

    list(): Observable<AccountType[]> {
        const url = `${this.baseUrl}/`;
        return this.http.get(url).pipe(
            // Adapt each item in the raw data array
            map((data: any[]) => data.map(item => this.adapter.adapt(item))),
        );
    }
}

this example may help more

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.