1. Overview
In this quick tutorial we’ll learn how to consume a RESTful API from an simple AngularJS front-end.
We’re going to display data in a table, create a resource, update it, and finally delete it.
2. The REST API
First, let’s take a quick look at our simple API – exposing a Feed resource with pagination:
- get paginated – GET /api/myFeeds?page={page}&size={size}&sortDir={dir}&sort={propertyName}
- create – POST /api/myFeeds
- update – PUT /api/myFeeds/{id}
- delete – DELETE /api/myFeeds/{id}
A quick note here is that pagination is using the following 4 parameters:
- page: index of requested page
- size: maximum number of records per page
- sort: the name of property used in sorting
- sortDir: the sorting direction
And here’s an example of what the Feed resource looks like:
{
"id":1,
"name":"baeldung feed",
"url":"/feed"
}
3. The Feeds Page
Now, lets take a look at our feeds page:
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js">
</script>
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular-resource.min.js">
</script>
<script th:src="@{/resources/ng-table.min.js}"></script>
<script th:src="@{/resources/mainCtrl.js}"></script>
<a href="#" ng-click="addNewFeed()">Add New RSS Feed</a>
<table ng-table="tableParams">
<tr ng-repeat="row in $data track by row.id">
<td data-title="'Name'" sortable="'name'">{{row.name}}</td>
<td data-title="'Feed URL'" sortable="'url'">{{row.url}}</td>
<td data-title="'Actions'">
<a href="#" ng-click="editFeed(row) ">Edit</a>
<a href="#" ng-click="confirmDelete(row.id) ">Delete</a>
</td>
</tr>
</table>
</div>
</body>
</html>
Note that we used ng-table to display data – more on that in the following sections.
4. An Angular Controller
Next, let’s have a look at our AngularJS controller:
var app = angular.module('myApp', ["ngTable", "ngResource"]);
app.controller('mainCtrl', function($scope, NgTableParams, $resource) {
...
});
Note that:
- We injected the ngTable module to use it for displaying our data in a user friendly table and handle pagination/sorting operations
- We also injected ngResource module to use it for accessing our REST API resources
5. An AngularJS DataTable
Let’s now have a quick look at the ng-table module – here’s the configuration:
$scope.feed = $resource("api/myFeeds/:feedId",{feedId:'@id'});
$scope.tableParams = new NgTableParams({}, {
getData: function(params) {
var queryParams = {
page:params.page() - 1,
size:params.count()
};
var sortingProp = Object.keys(params.sorting());
if(sortingProp.length == 1){
queryParams["sort"] = sortingProp[0];
queryParams["sortDir"] = params.sorting()[sortingProp[0]];
}
return $scope.feed.query(queryParams, function(data, headers) {
var totalRecords = headers("PAGING_INFO").split(",")[0].split("=")[1];
params.total(totalRecords);
return data;
}).$promise;
}
});
The API expects a certain style of pagination, so we need to customize that here in the table to match it. We’re using params out of ng-module and creat our own queryParams here.
A few additional notes about pagination:
- params.page() starts from 1 so we also need to make sure it becomes zero indexed when communicating with the API
- params.sorting() returns an object – for example {“name”: “asc”}, so we need to separate the key and value as two different parameters – sort, sortDir
- we extract the total element count from a HTTP header of the Response
6. More Operations
Finally, we can perform a lot of operations using ngResource module – $resource does cover the full HTTP semantics in terms of available operations. We can also define our custom functionality.
We have used query in the previous section to get the feeds list. Note that both get and query do GET – but query is used to handle an array response.
6.1. Add a New Feed
In order to add new feed we will use $resource method save – as follows:
$scope.feed = {name:"New feed", url: "http://www.example.com/feed"};
$scope.createFeed = function(){
$scope.feeds.save($scope.feed, function(){
$scope.tableParams.reload();
});
}
6.2. Update a Feed
We can use our own custom method with $resource – as follows:
$scope.feeds = $resource("api/myFeeds/:feedId",{feedId:'@id'},{
'update': { method:'PUT' }
});
$scope.updateFeed = function(){
$scope.feeds.update($scope.feed, function(){
$scope.tableParams.reload();
});
}
Note how we configured our own update method to send out a PUT request.
6.3. Delete a Feed
Finally, we can delete a feed by using delete method:
$scope.confirmDelete = function(id){
$scope.feeds.delete({feedId:id}, function(){
$scope.tableParams.reload();
});
}
7. AngularJs Dialog
Now, let’s see how to use ngDialog module to display simple form for adding/updating our feeds.
Here is our template, we can define it in a separate HTML page or in the same page:
<script type="text/ng-template" id="templateId">
<div class="ngdialog-message">
<h2>{{feed.name}}</h2>
<input ng-model="feed.name"/>
<input ng-model="feed.url"/>
</div>
<div class="ngdialog-buttons mt">
<button ng-click="save()">Save</button>
</div>
</script>
And then we will open our dialog to add/edit a feed:
$scope.addNewFeed = function(){
$scope.feed = {name:"New Feed", url: ""};
ngDialog.open({ template: 'templateId', scope: $scope});
}
$scope.editFeed = function(row){
$scope.feed.id = row.id;
$scope.feed.name = row.name;
$scope.feed.url = row.url;
ngDialog.open({ template: 'templateId', scope: $scope});
}
$scope.save = function(){
ngDialog.close('ngdialog1');
if(! $scope.feed.id){
$scope.createFeed();
} else{
$scope.updateFeed();
}
}
Note that:
- $scope.save() is called when user clicks Save button in our dialog
- $scope.addNewFeed() is called when user clicks Add New Feed button in feeds page – it initializes a new Feed object (without id)
- $scope.editFeed() is called when user wants to edit a specific row in Feeds table
8. Error Handling
Finally, let’s see how to handle response error messages using AngularJS.
In order to handle server error responses globally – instead of per request – we’ll register an interceptor to the $httpProvider:
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(function ($q,$rootScope) {
return {
'responseError': function (responseError) {
$rootScope.message = responseError.data.message;
return $q.reject(responseError);
}
};
});
}]);
And here’s our message representation in HTML:
<div ng-show="message" class="alert alert-danger">
{{message}}
</div>
9. Conclusion
This was a quick writeup of consuming a REST API from AngularJS.
The full implementation of this tutorial can be found in the github project – this is an Eclipse based project, so it should be easy to import and run as it is.