How to handle pagination and count with angularjs resources?

e-satis picture e-satis · May 9, 2013 · Viewed 16k times · Source

I have to build an angularjs client for an API outputting JSON like this:

{
  "count": 10,
  "next": null,
  "previous": "http://site.tld/api/items/?start=4"
  "results": [
    {
      "url": "http://site.tld/api/items/1.json",
      "title": "test",
      "description": "",
      "user": "http://site.tld/api/users/4.json",
      "creation_datetime": "2013-05-08T14:31:43.428"
    },
    {
      "url": "http://site.tld/api/items/2.json",
      "title": "test2",
      "description": "",
      "user": "http://site.tld/api/users/1.json",
      "creation_datetime": "2013-05-08T14:31:43.428"
    },
    {
      "url": "http://site.tld/api/items/3.json",
      "title": "test3",
      "description": "",
      "user": "http://site.tld/api/users/2.json",
      "creation_datetime": "2013-05-08T14:31:43.428"
    }
  ]
}

How can I make a $resource that maps to this ? If I use isArray=false, I'll get the entire blob as one object, usable for reading, but I can't call .put() on it. If I use isArray, it just doesn't work.

Is there any clean way to do this? Or should I go back to using $http?

Answer

joakimbl picture joakimbl · May 9, 2013

You have a couple of options. If you can change the server output you could add the meta info (count, next, previous) as header values instead of adding them in the response body.

Your second option is to transform the response with transformResponse. This is available as a $response configuration in angular v1.1.2 and later (the unstable branch):

var Data = $resource('./data.json',{},{
  list:{isArray:true,method:'get',
    transformResponse: function (data, headers) {
      return JSON.parse(data).results; 
   }}
});

If you don't want to use the unstable branch it is also possible to change the $http which $resource uses:

$http.defaults.transformResponse.push(function(data){
  if(data && data.results){
    return data.results;
  }
});

I've created a plunker with both examples: http://plnkr.co/edit/PmYotP0eo5k41Z6ZCxl4?p=preview

I'm not sure what the best approach for passing on the meta data to the rest of your application (if you need it). You could append it to the first result, or add it as a separate object - maybe not so elegant, but it'll get the job done.