AngularJS Framework : Creating a new service using Factory
Picture from How to structure large angularJS applications
The following sections are largely based on Introduction to Angular.js in 50 Examples (part 2).
We'll start from where we left off (Routes V - details page). In this section, unlike in the previous example where each view fetches the json data (picture below), we'll fetch json data just once by creating a new service using factory.
The Factory constructs a new service using a function with zero or more arguments (these are dependencies on other services). The return value of this function is the service instance created by the factory.
Note: All services in Angular are singletons. That means that the injector uses each recipe at most once to create the object. The injector then caches the reference for all future needs.
Two of the template files are here (country-list.html and country-detail.html).
Here is our main code (factory.html):
<html ng-app="countryApp"> <head> <meta charset="utf-8"> <title>Angular.js Example</title> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-route.min.js"></script> <script> var countryApp = angular.module('countryApp', ['ngRoute']); countryApp.config(function($routeProvider) { $routeProvider. when('/', { templateUrl: 'country-list.html', controller: 'CountryListController' }). when('/:countryName', { templateUrl: 'country-detail.html', controller: 'CountryDetailController' }). otherwise({ redirectTo: '/' }); }); countryApp.factory('countries', function($http){ return { list: function(callback){ $http.get('countries.json').success(callback); } }; }); countryApp.controller('CountryListController', function ($scope, countries){ countries.list(function(countries) { $scope.countries = countries; }); }); countryApp.controller('CountryDetailController', function ($scope, $routeParams, $http){ $http.get('countries.json').success(function(data) { $scope.country = data.filter(function(entry){ return entry.name === $routeParams.countryName; })[0]; }); }); </script> </head> <body> <div ng-view></div> </body> </html>
Note that we modified quite a few lines.
countryApp.factory('countries', function($http){ return { list: function(callback){ $http.get('countries.json').success(callback); } }; });
Here, we call factory on the countryApp module. The first argument (countries) of the factory is the name of the service. It returns an object that has a function called list. The function has a callback which will be called when the json data is loaded. In short, here we're introducing a factory called countries.
How about the controllers?
countryApp.controller('CountryListController', function ($scope, countries){ countries.list(function(countries) { $scope.countries = countries; }); });
We're using the name of the factory as a function parameter. In fact, we're injecting our own creation into a controller. Note that the countries is the object returned from the factory. Note also that we're using the list like countries.list, and the list is defined in the factory.
The next controller, CountryDetailController is also using the countries service:
countryApp.controller('CountryDetailController', function ($scope, $routeParams, $http){ $http.get('countries.json').success(function(data) { $scope.country = data.filter(function(entry){ return entry.name === $routeParams.countryName; })[0]; }); });
The rendered output of factory.html is the same as in the example of the previous tutorial. No changes in the rendered results but this one removes the redundancies regarding fetching json data.
AngularJS
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization