AngularJS Custom Actions for ExpressJS

In this tutorial video we’ll look at using an AngularJS Resource service to communicate between AngularJS and your ExpressJS controllers.

We’ll count the number of records in a mongoDB collection, and then return the result to an AngularJS controller to display on a view.

We’ll look at:
– Creating a new express method on a server controller – in order to count the number of records in our Customers collection,
– Creating a new express route
– Adding a custom action to an AngularJS service
– Calling the custom action from an Angular controller
– Displaying the result of the count in our view

Lastly, we also look at displaying the returned count within an ng-repeat using 2 way data binding!

Lets begin with the server side code, and then move onto the client side.

The Server Side

Customer Server Controller:

customers.server.controller.js

On the server side we use mongoose to interact with mongoDB and to get access to the Customer collection. We’re creating a new controller method exports.custCount


/**
 * Module dependencies.
 */
var _ = require('lodash'),
	path = require('path'),
	mongoose = require('mongoose'),
	Customer = mongoose.model('Customer'),
	errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller'));


/**
 * Count of Customers
 */
exports.custCount = function(req, res) {
	Customer.count({},
		function(err, customerCount) {
			if (err) {
				return res.status(400).send({
					message: errorHandler.getErrorMessage(err)
				});
			} else {
				console.log(customerCount);
				var data = {};
				data.count = customerCount;
				res.json(data);
			}
		});
};

To count the records, we can use the mongoose method Model.count, as Customer.count to count the number of records in the Customer collection.
After performing the query, the response returns either an error (as 'err'), or with the result of the count as customerCount.

Once we have access to the result, we can change it up (in this case assign it to the data object), and then return the result in json format: res.json(data).

For more examples of running mongoose queries, have a look at the mongoose doco and the mongoose API

Customer Server Route:

customers.server.routes.js
To hook the exports.custCount method in our express controller to an express route, we create a route/API: '/api/customers/custCount'.

When the route is called with a ‘GET’ request, we want express to look for the custCount method within the customers.server.controller file.


module.exports = function(app) {
	var customers = require('../controllers/customers.server.controller');
	app.route('/api/customers/custCount')
		.get(customers.custCount);
}

The Client Side

Customer Service:

customers.client.service.js
On the client side, we can call Express JS routes using a $resource Service. We can also add custom actions within our existing $resource Service.


//Customers service used to communicate Customers REST endpoints
angular.module('customers').factory('Customers', ['$resource',
	function($resource) {
		return $resource('api/customers/:customerId', { customerId: '@_id'
		}, {
			update: {
				method: 'PUT'
			},
			countCustomers: {
				method: 'GET',
				url: '/api/customers/custCount',
				isArray: false
			}
		});
	}
]);

In this example, we have a custom action called countCustomers, which will send a GET HTTP request to the url: '/api/customers/custCount', which is the same url as the one that our Express Route is listing out for in customers.server.routes.js.

Note that the $resource url and express API must match (between the service and the route) but the API doesn’t need to match the url of the current view that the user is on – i.e. you can call this API from any controller, regardless of the url that is pointed at in the browser.

Home Controller:

home.client.controller.js
Once we have a Service, in this case the Customers Service defined in customers.client.service.js, we can then add that service to any of our AngularJS controllers.

angular.module('core').controller('HomeController', ['$scope', 'Authentication', 'Customers',
	function($scope, Authentication, Customers) {
		// This provides Authentication context.
		$scope.authentication = Authentication;

        $scope.numOfCustomers = Customers.countCustomers();

        $scope.alerts = [
            {
                icon: 'glyphicon-user',
                colour:'btn-success',
                total: '20,408',
                totalNum: $scope.numOfCustomers,
                description: 'TOTAL CUSTOMERS'
            }...
        ];
	}
]);

Here we add the Customers Service to the HomeController, and now we can call the service using Customers., so to call the countCustomers method within the Customers Service, we can use Customers.countCustomers(), we can assign it to $scope.numOfCustomers (or this.numOfCustomers if you’re using Controller as syntax), and use that to pass the count to a view.

HTML View:

home.client.view.html
Our last step is to display the result of the customers count in a view.

<section data-ng-controller="HomeController">
 ...
        <h2>The number of customers: {{numOfCustomers.count}}</h2>
        <div class="col-sm-6" ng-repeat="alert in alerts">
 ...
               <div class="col-xs-8">
                    <h1>{{alert.totalNum || alert.total}}</h1>
                </div>
...

In this example, we have two ways of showing the result of the customer count, retrieved from the HomeController, firstly as {{numOfCustomers.count}} and secondly within an ng-repeat, where we show a static value if the count is not available

Hope that helped. Until next time! 😀

Category: Mean Stack

1 Comment

Let me know what you think

  • Krishna
    Reply

    Thanks for your tutorial as it is very helpful to build the dashboard. If possible, please create a new tutorial to demonstrate how we can use two or more MongoDB schema join (embedded documents).