The article presents recipe to create single page application with AngularJS & Spring MVC where different pages are required to do transactions with server using RESTful API. The demonstration is created on this page, http://hello-angularjs.appspot.com/angularjs-single-page-app-restful-apis.
Code samples and related concepts are presented for following requirements of single page app:
- Initially one page is loaded with side navigation.
- Clicking on side navigation loads new view (data) from server by consuming RESTful API using ngResource, $resource service with “query” action method
- Clicking on individual items link loads the related data from server, again by consuming RESTful API using ngResource, $resource service with “get” action method
- Submitting a set of data consumes a RESTful API and sends the data to the server for persistence. Here, $resource service with “save” action method is used.
The demo app presents a trivial app which allow users to do some of the following:
- Create new users
- Get all users
- Get users by Id
In this example, one userservice is created that does the RESTful transaction. This userservice is used in multiple different controllers used to load/manage different views.
Following are keys to creating AngularJS Single Page App that consumes RESTful APIs:
- Angular module dependencies
- Routing code that defines routes for different links.
- Code to manage the transactions with RESTful APIs. I created a custom User service that provides APIs to do transactions with RESTful APIs
- Controller code that defines how data will be retrieved/handled in each view
- Server side code to receive RESTful API request and send appropriate response
Following are two different modules that will be required to be included when creating app:
- ngRoute
- ngResource
Following is the code sample:
var userApp = angular.module("userApp", [ 'ngRoute', 'ngResource' ]);
You would also have to include following withinelement:
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular-route.js"></script> <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular-resource.js"></script>Routing Code
Following represents the routing code which defines how each link/path will be processed (controller, templateURL)
userApp.config(function($routeProvider) { $routeProvider.when('/users/new', { controller : 'NewUserCtrl', templateUrl : 'views/newuser.html' }).when('/users/:userId', { controller : 'UsersByIdCtrl', templateUrl : 'views/userbyid.html' }).when('/users', { controller : 'UsersCtrl', templateUrl : 'views/users.html' }).otherwise({ controller : 'SpaCtrl', templateUrl: 'views/spahome.html' }); });User Service – Transactions with RESTful APIs
Following code is used to userservice using AngularJS factory recipe. This userservice internally instantiates User class by passing $resource service to its constructor function. Note that $scope is passed to individual APIs/methods and that the value for model is set within each API. Once updated, the model values appear on the UI.
userApp.factory( 'userservice', [ '$resource', function( $resource ){ return new User( $resource ); }] ); function User( resource ) { this.resource = resource; this.createUser = function ( user, scope ) { // // Save Action Method // var User = resource('/users/new'); User.save(user, function(response){ scope.message = response.message; }); } this.getUser = function ( id, scope ) { // // GET Action Method // var User = resource('/users/:userId', {userId:'@userId'}); User.get( {userId:id}, function(user){ scope.user = user; }) } this.getUsers = function( scope ) { // // Query Action Method // var Users = resource('/users/all'); Users.query(function(users){ scope.users = users; }); } }AngularJS Controller Code for Different Views
// Controller when the main page/view loads userApp.controller("SpaCtrl", [ '$scope', function($scope) { } ]); // Controller for All Users View userApp.controller("UsersCtrl", [ '$scope','userservice', function($scope, userservice) { userservice.getUsers( $scope ); } ]); // Controller for New User View userApp.controller("NewUserCtrl", [ '$scope','userservice', function($scope, userservice) { userservice.getUsers( $scope ); $scope.createNewUser = function(){ var newuser = { 'firstname':$scope.firstname, 'lastname': $scope.lastname, 'address':$scope.address, 'email':$scope.email }; // Call UserService to create a new user // userservice.createUser ( newuser, $scope ); // Push new user to existing table column // $scope.users.push( newuser ); // Reset fields values // $scope.firstname=''; $scope.lastname=''; $scope.address=''; $scope.email=''; }; } ]); // Controller for Individual User View userApp.controller("UsersByIdCtrl", [ '$scope','userservice', '$routeParams', function($scope, userservice, $routeParams) { userservice.getUser($routeParams.userId, $scope); } ]);Spring MVC Controller Code for RESTful API
Following demonstrates the Spring MVC Controller code for three different RESTful APIs with URL written as part of RequestMapping value parameter:
All Users (/users/all)@RequestMapping(value = "/users/all", method = RequestMethod.GET) public @ResponseBody String getAllUsers( ModelMap model ) { String jsonData = "[{\"id\":\"3253123\",\"firstname\":\"Chris\",\"lastname\":\"Johnson\",\"address\":\"211, Geoffrey Drive\",\"city\":\"Newark\",\"phone\":\"999-888-6666\",\"email\":\"[email protected]\"},{\"id\":\"67643837\",\"firstname\":\"Bill\",\"lastname\":\"Derkson\",\"address\":\"201, Sleepy Hollow Drive\",\"city\":\"Newark\",\"phone\":\"999-777-2222\",\"email\":\"[email protected]\"}]"; return jsonData; }
New Users (/users/new)
@RequestMapping(value = "/users/new", method = RequestMethod.POST) public @ResponseBody String createNewUser( @RequestBody User user ) { // // Code processing the input parameters // String response = "{\"message\":\"Created New User - firstname: " + user.getFirstname() + ", lastname: " + user.getLastname() + ", address: " + user.getAddress() + ", email: " + user.getEmail()+"\"}"; return response; }
User By Id (/users/{id}
@RequestMapping(value = "/users/{id}", method = RequestMethod.GET) public @ResponseBody String getUsersById( @PathVariable("id") long userId ) { // // Code processing the input parameters // String response = "{\"id\":\""+ userId + "\",\"firstname\":\"FirstName\",\"lastname\":\"LastName\",\"address\":\"Some Address\",\"age\":\"SomeNo\",\"email\":\"[email protected]\"}"; return response; }
After having found the recipe for creating single page app that could consume RESTful APIs, I am not sure if I would be using any other way to create single page app other than the way described in this article. Please feel free to share your ideas/suggestions/thoughts.