Reputation: 1894
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.
Upvotes: 5
Views: 6759
Reputation: 42586
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}
});
Upvotes: 9
Reputation: 4885
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))),
);
}
}
Upvotes: 0
Reputation: 15443
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);
})
Upvotes: 2
Reputation: 9134
As mentioned in the comment please also map the array content
return e.map(entry => {'label': entry.name, 'value': entry.id});
Upvotes: 4