Code

Building a RESTful web service with AngularJS (and PHP) – More power with $resource

, , , 20 Comments

This is a two parts post about how to make RESTful requests through an AngularJS web application.

Index

The index of this brief series of posts is quite simple.

  • Backend setup was the first post in the series. It serves to introduce the RESTful web service to which the application, that I built, will send requests.
  • Now this last post, More power with $resource, covers how to deal with a RESTful web service through a web application built on AngularJS.

$http or $resource?

In all the posts about AngularJS that I wrote until now, everytime that it was necessary to make an asynchronous request to the server I used the $http service. So now, probably you’re asking yourself where do $resource come from.
$resource is a separate, optional module of AngularJS, built over $http. It allows to create a javascript object that represents the data model. In this way each operation computed on the object created through $resource, is performed also on the server.
$resource should be used instead of $http each time the web application has to deal with a RESTful web service.


var r = $resource(url, [defaultParameters], [customActions]);

/*
 - url: parameterized url template. 
   Parameters are prefixed by ":"; for example /book/:bookId
 - defaultParameters: it is an object containing default values 
    for url's parameter; for example { bookId: 42 }
 - customActions: it allows to extend the resource object with 
   custom actions; for example:

   {actionName: { method: '', params: {}, isArray: true/false }}

   - method: HTTP request method; one of (GET, POST, PUT, DELETE)
   - params: additional parameters.
   - isArray: true if the returned object for this action is an 
     array.
*/

console.info(r);
/*
 Now r offers the methods for the default set of resource actions 
 optionally extended with custom actions. 
 For example:

 r.get({bookId: 42}) sends a GET request to /book/42
*/

Start using $resource

As I said previously $resource is a separate module of AngularJS; it is defined in the angular-resource.js file, often downloaded with angular.js.
To use $resource there are three easy things to do:

  • Include the source file, immediatelly after the source of angular.js, and ideally before the end of the body.
    	
    <script type="text/javascript" src="angular.js"></script>
    <script type="text/javascript" src="angular-resource.js"></script>
    
    <!-- ... more javascript ... -->
    
    </body>
    
    
  • Include ngResource in the declation of your web application module.
    	
    var myApp = angular.module('myApp', ['ngResource']);
    
    
  • Inject $resource everywhere it will be used.

Now it’s possible to use $resourse, and start to take advantage of the possibility to create a javascript object that represents the data model.
The best choice is to wrap the javascript model object into an AngularJS service, in this way we’ll get each of the advantages of using services:


myApp.factory('Books', ['$resource', function($resource) {

	return $resource( '/book/:bookId', 
		{ bookId: '@bookId' }, { 
			loan: { 
				method: 'PUT', 
				params: { bookId: '@bookId' }, 
				isArray: false 
			} 
			/* , method2: { ... } */
		} );

}]);

At this point it is really simple to send requests to the web service, that we build in the previous post.
Everywhere it is possible to inject the Books service it is possible to write:


postData = { 
  "id": 42, 
  "title": "The Hitchhiker's Guide to the Galaxy", 
  "authors": ["Douglas Adams"] 
}
Books.save({}, postData);
// It sends a POST request to /book. 
// postData are the additional post data

Books.get({bookId: 42});
// Get data about the book with id = 42

Books.query();
// It is still a GET request, but it points to /book, 
// so it is used to get the data about all the books

Books.loan({bookId: 42});
// It is a custom action.
// Update the data of the book with id = 42

Books.delete({bookId: 42});
// Delete data about the book with id = 42

Bruno

I'm Bruno Scopelliti, web developer from Bologna, Italy. I use this space to share my experiences, experiments and thoughts. I'm also on Google+, Twitter, and LinkedIn.

More Posts

Standard
  • http://www.silentworks.co.uk Silent Works

    I am not sure if something changed in the version of $resource that you are using but you can do Books.save(postData); without the first param being an empty object. Nice write-up on $resource either way. It would be great if you could add the version of Angular and ngResource you use in each tutorial.

  • Anton Gribanov

    Hi Bruno.
    Don’t we need key “id” in postData object to be “bookId”?

    • http://brunoscopelliti.com/ Bruno Scopelliti

      Hi Anton,
      Not necessarily, since it depends on the way I call it in the backend…
      However, since everywhere I called it “bookId”, it’s a good idea to mantain the same name…
      Thanks

  • bmcferren

    one thing that may help new users here is the differentiation between JSONP and get (or query for that matter)

  • codedungeon

    So, this is all fine and good. But what if the rest service you are communicating with require authentication to perform post and delete actions. How do you configure the resource object to contain the appropriate user credentials before executing the appropriate call?

    • http://brunoscopelliti.com/ Bruno Scopelliti

      Hi,
      I really appreciate this question…
      The fast answer is that you can add a new header to the $http.defaults.headers.common array…
      However I wrote a post to cover this topic with more detail… I will publish it tomorrow.

  • 二ツ岩

    Check out Restangular — makes much more sense.

  • Robert K

    Nice article, but AngularJS code without matching unit tests, I’m pretty sure there is some law against that! ;)

  • nidhirao.arien

    Do we know whether angularjs can make SOAP web calls as well?

  • Stanley Nguyen

    how can we dynamically set url in $resource? I tried to pass in with $scope but it fails.

  • propidadrakesh

    excellent post nice artcile ,thanks for sharing the article,very good information Web Development

  • flatsteve

    Hi Bruno, great article and blog! Excuse me if this is a silly question but how do you handle updating the view after the HTTP request? Does Angular provide a way to do this on success? Any help would be greatly appreciated!

  • pyner

    How I can handler http status code with $resource ?

  • Courtney Nguyen

    Could I use the $resource object to post form data, like a file object? I want to catch the post and then with the request, use business logic on it. Is this how I would do that?

  • Prateek Jain

    awesome dude,

  • Murali M

    yes this is a usfull blog thank u….

  • http://www.markdejong.com/ Mark de Jong

    Does $resource usually allow ‘PUT’ actions? I am now setting up an Angular service using the structure you did, but my PUT doesn’t work. Only GET at the moment, still have to try POST.

  • XP

    Hi!

    /Clients/:idClient/Contacts/:idContact

    Thanks

    how I do something like this?