Skip to main content

Using Angular.js Factories to Get Remote Data

In this post, I’d like to show the differences between using an Angular.js factory to get local JSON data vs remote data via an AJAX call.

For this example, I’m assuming that we have a JSON dataset that describes different types of fruit, for example:

{
  "fruits": [
    {
      "id": "1",
      "name": "Apple"
    },
    {
      "id": "2",
      "name": "Orange"
    }
  ]
}


At it’s simplest, an Angular.js view to iterate over this data could look like the following HTML:


<!doctype html>
<html lang="en" ng-app="fruitsApp">
<head>
<title>Angular Sample App</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script src="app.js"></script>
</head>

  <body>
    <div ng-controller="fruitsController">
      <ul>
        <li ng-repeat="fruit in fruits"></li>
      </ul>
    </div>
  </body>
</html>


A Hardcoded Angular.js Controller and Factory


In the HTML view, we can see that an Angular.js controller called fruitsController is being used within a module called fruitsApp. We’re then using ng-repeat to iterate through a collection of fruit and add them into a simple HTML list.

If we wanted to get data locally rather than via HTTP, we could declare a controller and factory as follows:


var fruitsApp = angular.module('fruitsApp', [])

fruitsApp.factory('fruitsFactory', function() {
  return {
    getFruits: function() {
      return  [{"id": "1","name": "Apple"}, {"id": "2","name": "Orange"}];
    },
  };
});

fruitsApp.controller('fruitsController', function($scope, fruitsFactory) {
  $scope.fruits = fruitsFactory.getFruits();
});

This is a very simple controller and factory. The fruitsController returns a view model which is populated from the fruitsFactory, which simply has a hardcoded static list of fruit.

A Dynamic Angular.js Controller and Factory Using AJAX

The above exampe will work for getting data, but isn’t of much use for dynamically generated content. For dynamic content, we need to make an HTTP request to get our data, for example via a REST call.

To make a HTTP call via an Angular.js factory, we need to pass the $http object into the factory and then make a call to the remote HTTP request using the $http.get() method.

var fruitsApp = angular.module('fruitsApp', [])

fruitsApp.factory('fruitsFactory', function($http) {
  return {
    getFruitsAsync: function(callback) {
      $http.get('fruits.json').success(callback);
    }
  };
});

fruitsApp.controller('fruitsController', function($scope, fruitsFactory) {
  fruitsFactory.getFruitsAsync(function(results) {
    console.log('fruitsController async returned value');
    $scope.fruits = results.fruits;
  });
});

In this example, you can see that the controller makes a request to the factory which then calls an asynchronous function ($http.get) to get the data. When this asynchronous function completes successfully, it calls back to an anonymous function in the controller and populates the view model.

Comments

  1. I notice getFruitsAsync takes a callback parameter. Would a "more Angular" way of doing it be to just return the result of the http.get call, which is a promise object, so the calling function can handle the callback, along with any error conditions?

    ReplyDelete
  2. I agree. If you are just binding the result to the $scope object, angular is smart enough to understand a promise and defer the promise then bind the data when it appears. So, instead of doing a callback, you can literally just return the promise itself and set it to the $scope, like this: $scope.fruits = fruitsFactory.getFruitsAsync() and then in the factory return $http.get('fruits.json');

    ReplyDelete
  3. […] In this post, I’d like to show the differences between using an Angular.js factory to get local JSON data vs remote data via an AJAX call. To make a HTTP call via an Angular.js factory, we need to pass the $http object into the factory and then make a call to the remote HTTP request using the $http.get() method. In this example, you can see that the controller makes a request to the factory which then calls an asynchronous function ($http.get) to get the data. When this asynchronous function completes successfully, it calls back to an anonymous function in the controller and populates the view model.  […]

    ReplyDelete
  4. Been looking for an article like this for awhile now. Glad I found it. I assume that this is the proper way to handle Reqeusts via AJAX. I know you are not suppose to use the controller for DOM manipulation and things of that nature but I suppose that making these Requests are okay to handle in the controllers via a Factory, Correct or No?

    ReplyDelete
  5. but how will you handle errors?

    ReplyDelete
  6. Thank you so much for this post! I have been looking for a simple example like this for hours. All of the examples I've seen except this one don't work. So, thanks!

    ReplyDelete
  7. You'd have to do the promise shit I guess.. https://github.com/kriskowal/q#handling-errors

    Sometimes I just want to be able to do `q.prenuptial(cb)`

    Anyways, great article, thanks!

    ReplyDelete
  8. Thank you thank you thank you. I spent all day reading stackoverflow posts and trying to learn up on factories and services and yada yada yada. All I wanted was one useful example of how to make a factory around the $http service that I already had in my controller and help it all make sense!

    The key here, is that when defining your controller you changed the second argument which was $http (when there was no factory and the $http was used directly in the controllwer) into your factory instance fruitsFactory.

    ReplyDelete
  9. In terms of handling errors - have a look at this article - it's a working example of getting an error message from the factory into the controller.

    http://sravi-kiran.blogspot.com/2013/03/MovingAjaxCallsToACustomServiceInAngularJS.html

    ReplyDelete
  10. David,

    I seriously just started looking into angular, I haven't even finished the phones tutorial. But looking into angular two days ago and finding this post today was perfect timing. So thanks.

    ReplyDelete
  11. thanks...................

    ReplyDelete
  12. Hi Thanks for the sample, i was trying to use one controller for multiple html section and was working successfully , here is the demo http://jsfiddle.net/tomalex0/z6fEf/4/

    Next thing i wanted was to do a ajax request and load the multuple html section

    ReplyDelete
    Replies
    1. Solved
      http://stackoverflow.com/questions/22368267/single-controller-for-multiple-html-section-and-data-from-ajax-request-angularjs

      Delete

Post a Comment

Popular posts from this blog

Creating a Joke Application in React

Introduction I've recently started learning React. I've been a backend developer for a long time, but have started to love doing client side work. As they say, the best way to learn is to practise. So here is a simple joke application that I've written in React. The source code for the application can be found on GitHub at: https://github.com/doobrie/react-joke Creating the project Whilst practising, I've quite often created projects from scratch, but this is quite tedious as the same steps need to be taken for each project. I needed to create the project structure, configure Babel, write some control scripts etc. Instead of doing that this time, I've used the create-react-app tool to scaffold the basics of an application. npx create-react-app This sets up everything that you need to get started with a React app. Coding As this is a simple project, I've created one react component, function app() . I've created this as a functional c...

Changing Default Search Provider in Firefox on Linux Mint

On Linux Mint, the default version of Firefox is installed and configured to allow the following search engines to be queried directly from the address bar: Yahoo! Startpage DuckDuckGo Wikipedia Mint defines these as the default available set of search engines based upon 3 criteria (funding to Linux Mint, privacy support and whether the search engine is non-commercial). Other search engines such as Google, Bing or Twitter, etc. can easily be added into the default version of Firefox however. To add a different search provider, browse to Search Engines At the bottom of the page, click on the icon of the requested search engine, then click on the ... button in the URL bar and select the Add Search Engine option. You then have the option to change the default search engine within Firefox preferences to your new choice.

The new Eclipse logo

In a blog post today, Ian Skerrett has announced the new logo for Eclipse. Last fall we [The Eclipse Foundation] started a process to  update the Eclipse logo . The existing logo had not been change since Eclipse was launched and it was showing its age. I am happy to announce we have finished the process and am pleased to introduce the updated Eclipse logo. The new logo has a fresh modern look to it, which I think is a good improvement and will stand Eclipse in good stead for the future. The new logo will be included with the next Eclipse release train, Luna, and gradually rolled out across the Eclipse site and projects. What do you think?  Do you like the new logo?  Add your comments below.