RESTful endpoints often expose CRUD operations that are accessible by calling different HTTP methods on a set of similar URLs. The code that interacts witch such endpoints is usually straightforward but tedious to write. The $resource service allows us to eliminate the repetitive code. We can also start to operate on a higher abstraction level and think of data manipulation in terms of objects (resources) and method calls instead of low-level HTTP calls.

Note

The $resource service is distributed in a separate file (angular-resource.js), and resides in a dedicated module (ngResource). To take advantage of the $resource service we need to include the angular-resource.js file and declare dependency on the ngResource module from our application’s module.

To see how easy is to interact with the RESTful endpoint using the $resource service we are going to construct an abstraction over the collection of users exposed as a RESTfulservice by the MongoLab:

angular.module('resource', ['ngResource'])

  .factory('Users', function ($resource) {

return 
$resource('https://api.mongolab.com/api/1/databases/ascrum/
   collections/users/:id', {
      apiKey:'4fb51e55e4b02e56a67b0b66',
      id:'@_id.$oid'
    });
  })

We start by registering a recipe (a factory) for the User constructor function. But notice that we don’t need to write any code for this constructor function. It is the $resource service that will prepare implementation for us.

The $resource service will generate a set of methods that make it easy to interact with a RESTFul endpoint. For example, querying for all the users in the persistence store is as simple as writing:

  .controller('ResourceCtrl', function($scope, Users){
    $scope.users = Users.query();
  });

What will happen upon the call to the User.query() method is that $resource generated code is going to prepare and issue an $http call. When a response is ready the incoming JSON string will get converted to a JavaScript array where each element of this array is of type Users.

Note

Calls to the $resource service return a generated constructor function augmented with methods to interact with a RESTful endpoint: query, get, save and delete.

angularjs requires very little information to generate a fully functional resource. Let’s examine the parameters of the $resource method to see what input is required and what can be customized:

$resource('https://api.mongolab.com/api/1/databases/ascrum/collections/users/:id', {
      apiKey:'4fb51e55e4b02e56a67b0b66',
      id:'@_id.$oid'
    });

The first argument is a URL or rather a URL pattern. The URL pattern can contain named placeholders starting with the colon character. We can specify only one URL pattern which means that all HTTP verbs should use very similar URLs.

Tip

If your back-end uses a port number as part of the URL, the port number needs to be escaped while supplying the URL pattern to the $resource call (For example, http://example.com\\:3000/api). This is required since a colon has a special meaning in the $resource‘s URL pattern.

The second argument to the $resource function allows us to define default parameters that should be sent with each request. Please note that here by “parameters” we mean both placeholders in a URL template, and standard request parameters sent as a query string. angularjs will try first to “fill holes” in the URL template, and then will add remaining parameters to the URL’s query string.

The default parameters can be either static (specified in a factory) or dynamic, taken from a resource object. Dynamic parameter values are prefixed with a @ character.

Constructor-level and instance-level methods

The $resource service automatically generates two sets of convenience methods. One set of methods will be generated on the constructor-level (class-level) for a given resource. The aim of those methods is to operate on collections of resources or cater for the situation where we don’t have any resource instance created. The other set of methods will be available on an instance of a particular resource. Those instance-level methods are responsible for interacting with one resource (one record in a data store).

Constructor-level methods

The constructor function generated by the $resource has a set of methods corresponding to different HTTP verbs:

  • Users.query(params, successcb, errorcb): It issues an HTTP GET request and expects an array in the JSON response. It is used to retrieve a collection of items.
  • Users.get(params, successcb, errorcb): It issues an HTTP GET request and expects an object in the JSON response. It is used to retrieve a single item.
  • Users.save(params, payloadData, successcb, errorcb): It issues an HTTP POST request with request body generated from the payload.
  • Users.delete(params,successcb, errorcb) (and its alias: Users.remove): It issues an HTTP DELETE request.

For all the methods listed earlier the successcb and errorcb denote a success and error callback functions, respectively. The params argument allows us to specify per-action parameters that are going to end up either as part of the URL or as a parameter in a query string. Lastly, the payloadData argument allows us to specify the HTTP request body where appropriate (POST and PUT requests).

Advertisements