Using Services to Share Data Between Controllers

Services provide an easy way for us to share data and functionality throughout our app. The services we create are singletons that can be injected into controllers and other services, making them the ideal place for writing reusable code.

Let's start with the following code:

<!DOCTYPE html>
<html>
  <head>
    <title>AngularJS Services</title>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.5/angular.min.js"></script>
    <script type="text/javascript" src="app.js"></script>
  </head>
  <body>
    <div ng-app="app">
      <h1>Services</h1>
    </div>
  </body>
</html>

In this example, we'll be creating a service for storing messages, and two controllers, one for rendering a list of messages, and another for adding more messages to the list.

Let's set up our angular module, and create our service and call it messages

angular.module('app', []);

angular.module('app').factory('messages', function(){

});

Create and return and empty object called messages. This is the object that dependencies of this service will receive.

angular.module('app').factory('messages', function(){
  var messages = {};

  return messages;
});

Create a property list on messages, and set it to an empty array. This is where we will be storing our messages.

angular.module('app').factory('messages', function(){
  var messages = {};

  messages.list = [];

  return messages;
});

Create a function add on messages that will add provided messages to our list.

angular.module('app').factory('messages', function(){
  var messages = {};

  messages.list = [];

  messages.add = function(message){
    messages.list.push({id: messages.list.length, text: message});
  };

  return messages;
});

Now that our service is ready, let's create a couple controllers to make use of it.

Create a controller called ListCtrl that injects our messages service, and exposes the list from our service to our view.

angular.module('app').controller('ListCtrl', function (messages){
  var self = this;

  self.messages = messages.list;
});

Within a div that uses the ListCtrl that we just created, use the ng-repeat directive to display our list of messages.

<div ng-app="app">
  <h1>Services</h1>

  <div ng-controller="ListCtrl as list">
    <p ng-repeat="message in list.messages">{{ message.id }}: {{ message.text }}</p>
  </div>
</div>

The ng-repeat directive iterates over collections within our view, repeating the contents within the element where ng-repeat is used. Since our list of messages is currently empty, let's create another controller to help us populate the list.

Create a controller named PostCtrl that also injects our messages service. This controller will also contain an addMessage function that uses the add function we made in our service.

angular.module('app').controller('PostCtrl', function (messages){
  var self = this;

  self.addMessage = function(message){
    messages.add(message);
  };
});

Create a form underneath our list using PostCtrl

</div>
<div ng-controller="PostCtrl as post">
  <form ng-submit="post.addMessage(post.newMessage)">
    <input type="text" ng-model="post.newMessage">
    <button type="submit">Add Message</button>
  </form>
</div>

Set a newMessage within PostCtrl to get a default message, set newMessage to an empty string after calling message.add to clear out the input field after it's been submitted.

angular.module('app').controller('PostCtrl', function (messages){
  var self = this;

  self.newMessage = 'Hello World!';

  self.addMessage = function(message){
    messages.add(message);
    self.newMessage = '';
  };
});