banner



How To Create A Factory In Angularjs

Using an AngularJS Factory to Interact with a RESTful Service

What's covered in this Post?

  • Creating a RESTful Service
  • Creating an AngularJS Module
  • Creating a Factory
  • Creating a Controller
    f

AngularJS provides a great framework for building robust Single Page Applications (SPAs) and provides built-in support for routing, MV*-style programming, services and factories, modules, testing, and much more. Although Angular can consume virtually any HTTP resource, in this post I'm going to focus on using it to consume a RESTful API created using ASP.NET Web API (note that any back-end service could be used). If you've worked with jQuery before then you're used to calls such as $.getJSON() or $.ajax(). Although Angular plays really well with jQuery, it has built-in HTTP functionality that can be used out of the box and a way to encapsulate data functionality using factories or services.

Here's a quick review of some of the key players in AngularJS. I'll touch on modules, routes, factories, and controllers in this post and discuss how data functionality (such as RESTful service calls) can be encapsulated in factories that can be called from controllers.

image


Let's kick things off by taking a look at a basic backend service written using ASP.NET Web API and then walk through several AngularJS features including a factory that talks to the service.

Creating a RESTful Service

ASP.NET Web API is a great back-end framework for exposing data to a variety of clients. Although I'll focus on how JSON data can be exposed in this post, it can be used to serve up a variety of formats ranging from XML to images to custom formats. Here's an example of a simple service that exposes customer and order resources to clients. When the service is called from Web clients it will automatically return JSON data.

            public            class            CustomersController : ApiController     {         ICustomerRepository _Repository;            public            CustomersController()         {            //CustomerRepository could be injected if desired            _Repository =            new            CustomerRepository();         }            // GET api/customers            public            HttpResponseMessage Get()         {             var custs = _Repository.GetCustomers();            if            (custs ==            null)            throw            new            HttpResponseException(HttpStatusCode.NotFound);            return            Request.CreateResponse<IEnumerable<Customer>>(HttpStatusCode.OK, custs);         }            // GET api/customers/5            public            HttpResponseMessage Get(int            id)         {             var cust = _Repository.GetCustomer(id);            if            (cust ==            null)            throw            new            HttpResponseException(HttpStatusCode.NotFound);            return            Request.CreateResponse<Customer>(HttpStatusCode.OK, cust);         }            // POST api/customers            public            HttpResponseMessage Post([FromBody]Customer cust)         {             var newCust = _Repository.InsertCustomer(cust);            if            (newCust !=            null)             {                 var msg =            new            HttpResponseMessage(HttpStatusCode.Created);                 msg.Headers.Location =            new            Uri(Request.RequestUri + newCust.ID.ToString());            return            msg;             }            throw            new            HttpResponseException(HttpStatusCode.Conflict);         }            // PUT api/customers/5            public            HttpResponseMessage Put(int            id, [FromBody]Customer cust)         {             var status = _Repository.UpdateCustomer(cust);            if            (status)            return            new            HttpResponseMessage(HttpStatusCode.OK);            throw            new            HttpResponseException(HttpStatusCode.NotFound);         }            // DELETE api/customers/5            public            HttpResponseMessage Delete(int            id)         {             var status = _Repository.DeleteCustomer(id);            if            (status)            return            new            HttpResponseMessage(HttpStatusCode.OK);            throw            new            HttpResponseException(HttpStatusCode.NotFound);         }          [HttpGet]            public            List<Order> Orders(int            custID)         {             var orders = _Repository.GetOrders(custID);            if            (orders ==            null)            
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound)); return orders; } }


Looking through the code you can see that all of the main players are there including methods to handle GET, PUT, POST, and DELETE operations. Each method relies on a repository object behind the scenes to handle interacting with the actual data source. There are a lot of articles out there on using the ASP.NET Web API to build services so I won't go into more detail here. Check out the Web API site for additional information.

Now that you've seen the service let's switch to the client-side and talk about how AngularJS can be used to consume the service.

Creating an AngularJS Module


AngularJS provides several different options for encapsulating data functionality including services, factories, and providers. In this example I'll discuss factories (my personal favorite) and another object built-into the framework named $http. Before jumping into the factory code, let's take a quick look at the module that's configured for the application that I'll be discussing throughout this post:

            var            app = angular.module('customersApp', ['ngRoute']);  app.config(['$routeProvider',            function            ($routeProvider) {      $routeProvider.when('/', {         controller:            'customersController',         templateUrl:            '/app/views/customers.html'            })     .otherwise({ redirectTo:            '/'            });  }]);


In this example a customersApp module is created that acts as a container for other components used in the application such as the factory that will be discussed next. Notice that in addition to defining the cutomersApp module, the code also references the ngRoute module which handles routing. This module is found in a file named angular-route.js which is new in AngularJS 1.2 – see my previous post for additional information.

Once the module is defined it's used to configure routing for the application. This is done by calling the module's config() function which accepts a $routeProvider object. In this simple example a single route is defined to handle the root path but additional routes can certainly be defined using the $routeProvider.when() function.

Now that the module is created it's time to take a look at how a factory can be created and used to call the ASP.NET Web API service.

Creating a Factory

Although AngularJS controllers can call directly into back-end services, I prefer to put that type of functionality into factories so that it's more re-useable and easier to maintain. The application discussed here relies on a factory named dataFactory to make calls into the ASP.NET Web API service.

If you're new to factories they can be created by calling the angular.module('YourModule"').factory() function (note that modules can also create services, providers, values, and constants):

image

A factory is responsible for creating and returning an object that can be used to work with data, validate business rules, or perform a variety of other tasks. Angular factories are singletons by default so the object returned by a factory is re-used by the application.

Here's an example of a factory that handles GET, PUT, POST, and DELETE calls to the ASP.NET Web API service. The factory creates an object that handles making calls to the server.

angular.module('customersApp')     .factory('dataFactory', ['$http',            function($http) {            var            urlBase =            '/api/customers';            var            dataFactory = {};      dataFactory.getCustomers =            function            () {            return            $http.get(urlBase);     };      dataFactory.getCustomer =            function            (id) {            return            $http.get(urlBase +            '/'            + id);     };      dataFactory.insertCustomer =            function            (cust) {            return            $http.post(urlBase, cust);     };      dataFactory.updateCustomer =            function            (cust) {            return            $http.put(urlBase +            '/'            + cust.ID, cust)     };      dataFactory.deleteCustomer =            function            (id) {            return            $http.delete(urlBase +            '/'            + id);     };      dataFactory.getOrders =            function            (id) {            return            $http.get(urlBase +            '/'            + id +            '/orders');     };            return            dataFactory; }]);


The $http object is injected into the factory at runtime by AngularJS and used to make Ajax calls to the server. Looking through the code you can see that it exposes get(), post(), put(), and delete() functions that make it a piece of cake to work with RESTful services. Because the functions defined in the factory don't know what to do with the data they handle, each one returns a promise that can be wired up to callback functions by the caller.

As mentioned earlier, factories are singletons by default so the object returned by the factory can be re-used over and over by different controllers in the application. While AngularJS services can also be used to perform this type of functionality, a service returns an instance of itself (it's also a singleton) and uses the "this" keyword as a result. Factories on the other hand are free to create their own objects inside of the factory function and return them. To make this more clear let's compare the factory shown earlier to a service.

Here's an example of a service named dataService. Note that the function defined in the service is the object returned to the caller rather than an object defined inside of the function as with a factory.

angular.module('customersApp')     .service('dataService', ['$http',            function            ($http) {            var            urlBase =            '/api/customers';            this.getCustomers =            function            () {            return            $http.get(urlBase);         };            this.getCustomer =            function            (id) {            return            $http.get(urlBase +            '/'            + id);         };            this.insertCustomer =            function            (cust) {            return            $http.post(urlBase, cust);         };            this.updateCustomer =            function            (cust) {            return            $http.put(urlBase +            '/'            + cust.ID, cust)         };            this.deleteCustomer =            function            (id) {            return            $http.delete(urlBase +            '/'            + id);         };            this.getOrders =            function            (id) {            return            $http.get(urlBase +            '/'            + id +            '/orders');         };     }]);

Creating the Controller

Now that the factory is created a controller can use it to make calls to the ASP.NET Web API service. Here's an example of a controller named customersController that relies on the dataFactory for data retrieval and manipulation. All of the dataFactory functions return a promise which is resolved by the controller using the then() function. Once data is returned from the factory (assuming it works) the $scope is updated which will drive the user interface.

angular.module('customersApp')     .controller('customersController', ['$scope',            'dataFactory',            function            ($scope, dataFactory) {      $scope.status;     $scope.customers;     $scope.orders;      getCustomers();            function            getCustomers() {         dataFactory.getCustomers()             .then(function            (response) {                 $scope.customers = response.data;             },            function            (error) {                 $scope.status =            'Unable to load customer data: '            + error.message;             });     }      $scope.updateCustomer =            function            (id) {            var            cust;            for            (var            i = 0; i < $scope.customers.length; i++) {            var            currCust = $scope.customers[i];            if            (currCust.ID === id) {                 cust = currCust;            break;             }         }           dataFactory.updateCustomer(cust)           .then(function            (response) {               $scope.status =            'Updated Customer! Refreshing customer list.';           },            function            (error) {               $scope.status =            'Unable to update customer: '            + error.message;           });     };      $scope.insertCustomer =            function            () {            //Fake customer data            var            cust = {             ID: 10,             FirstName:            'JoJo',             LastName:            'Pikidily'            };         dataFactory.insertCustomer(cust)             .then(function            (response) {                 $scope.status =            'Inserted Customer! Refreshing customer list.';                 $scope.customers.push(cust);             },            function(error) {                 $scope.status =            'Unable to insert customer: '            + error.message;             });     };      $scope.deleteCustomer =            function            (id) {         dataFactory.deleteCustomer(id)         .then(function            (response) {             $scope.status =            'Deleted Customer! Refreshing customer list.';            for            (var            i = 0; i < $scope.customers.length; i++) {            var            cust = $scope.customers[i];            if            (cust.ID === id) {                     $scope.customers.splice(i, 1);            break;                 }             }             $scope.orders =            null;         },            function            (error) {             $scope.status =            'Unable to delete customer: '            + error.message;         });     };      $scope.getCustomerOrders =            function            (id) {         dataFactory.getOrders(id)         .then(function            (response) {             $scope.status =            'Retrieved orders!';             $scope.orders = response.data;         },            function            (error) {             $scope.status =            'Error retrieving customers! '            + error.message;         });     }; }]);

Summary

AngularJS has all of the building block components needed to integrate with back-end services. In this post you've seen how the $http object can be used to call a RESTful ASP.NET Web API service without writing a lot of code. You've also seen how data functionality can be encapsulated into a factory (or service) so that it can be re-used throughout an application. Keep in mind that although I used ASP.NET Web API in this example, the same general AngularJS code could be used to call a different back-end service created using Node.js, Python, or a variety of other languages/frameworks. Although the sample shown here is quite simple, I hope it gets you started using AngularJS and back-end services.

A project that shows this type of code in action can be found at https://github.com/DanWahlin/CustomerManagerStandard.


Check out my other posts on AngularJS

How To Create A Factory In Angularjs

Source: https://weblogs.asp.net/dwahlin/using-an-angularjs-factory-to-interact-with-a-restful-service

Posted by: proutopeashom96.blogspot.com

0 Response to "How To Create A Factory In Angularjs"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel