The back-end team I am working with implemented a REST API which returns collections as object (instead of array).
For example, calling GET /some_resources
would return:
{
id_1: {
p1: "lorem",
p2: 4
},
id_2: {
p1: "ipsum",
p2: 2
},
id_n: {
p1: "sic",
p2: 7
}
}
This structure is limiting to work with in Angular as you can't leverage the ng-repeat directive for instance (e.g orderBy and filter do not work with object).
For the previous example, ideally, I would rather expect an array of objects:
[
{id: "id_1", p1: "lorem", p2: 4},
{id: "id_2", p1: "ipsum", p2: 2},
{id: "id_n", p1: "sic", p2: 7}
]
This would allow to directly work with the object returned by the ngResource service and sent it back without touching its structure. It would also allow to fully use the ng-repeat directive.
When I asked the back-end team to change the structure of their response of collections from object to array, they argued that the API consumer should not lead the design of the structure for the response.
I partially agree with their argument, so for now, the only solution I found consist in transforming the object into an array, work with this object into my scope and retransform the array back to the original object structure, before sending it back to the API.
This leads to a lot of code boilerplate and I am wondering if there is an "angular way" to deal with this situation.
"they argued that the API consumer should not lead the design of the structure for the response"
Argue back - If the only consumer of the API is the front end currently, then they have time to put it in the proper format before other consumers are added. That data is perfectly suited to be an array instead of an object. I don't know how big your data set could potentially be but one thing you don't want to be doing in the future is manipulating objects - large or small - on the front end. Browsers have limited resources, servers can always have resources added.
Angular JS's ng-repeat
don't work well with objects, and collections should be arrays.
Your API Team is wrong, they are not building a RESTful API if they do not implement it the way the community use and create it. APIs should be built for the benefit of the consumer, it is an Interface just as like UI is built for the users.
And you are right to argue that it should be an array instead of an object. Here's one way of designing an API that is built by a community of experts: ebook
There are so many libraries that already work with RESTful APIs very well, if your backend will not implement the API correctly, you won't be able to use those great libraries created by the community. Plus, your future consumers will have a hard time using the API and will avoid using your product as a third party app
Update
let resource = {
id_1: {
p1: "lorem",
p2: 4
},
id_2: {
p1: "ipsum",
p2: 2
},
id_n: {
p1: "sic",
p2: 7
}
}
let model = [];
Object.keys(resource).forEach(
key=>{
let o = resource[key];
o['id'] = key;
model.push(o)
}
);
After applying this to your resource, the output will be an array, with keys id
, p1
, p2
in compliance with your preferred format. Once you're done working with the model, you can get it back in its original format:
let original={};
model.forEach(o => original[o.id] = {p1:o.p1, p2:o.p2});
Original Answer
I don't know of an "Angular way". I use the code below to handle similar situations. This is typescript but could easily be adapted to javascript. It was inspired by David Sherret's code
getObjValues(e: any) {
return Object.keys(e).map(k => e[k]);
}
let resource = {
id_1: {
p1: "lorem",
p2: 4
},
id_2: {
p1: "ipsum",
p2: 2
},
id_n: {
p1: "sic",
p2: 7
}
}
let model = getObjValues(resource)
model
will be an array of elements with keys p1
and p2
. If you need to recover the original object you'll need more code though both to save the initial id_1
, id_2
and to reconstruct the original object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With