Написание сервисов в Angular.js

Illustration of a person sitting on the floor, against a wall, engrossed in reading a tablet, with a subtle color gradient in the background. Illustration of a person sitting on the floor, against a wall, engrossed in reading a tablet, with a subtle color gradient in the background.

В предыдущей статье мы оживили список транзакций и добавили возможность добавлять новые транзакции. Тем не менее, как мы видим в боковом меню нашего приложения, общая сумма денег никак не связана с транзакциями. На самом деле, это просто текст, прописанный в html коде.

В этой статье мы рассмотрим сервисные объекты, доступные в Angular.js. Мы будем использовать сервисы как единое место для доступа к нашим транзакциям, что позволит нам получить эти данные в разных контроллерах. Так же мы познакомимся с Dependency Injection в Angular.js.

В Angular.js доступен целый зоопарк различных типов сервисных объектов. Наиболее популярными из них являются factory и service. Каждый такой сервис является синглтоном, то есть существует всего один экземпляр конкретного сервиса. Это идеально вписывается в наши условия: единая точка доступа к транзакциям, доступная из любых контроллеров.

Сегодня мы будем использовать factory, и скоро вы поймёте почему.

Начнём с добавления нового файла: src/components/transactions_store.service.js со следующим содержимым:

// src/components/transactions_store.service.js
angular.module('ngmkdev').factory('TransactionsStore', function() {
  return {
    transactions: []
  }
});

В отличии от контроллеров, с сервисами мы обладаем большей свободой в выборе имени. В данном случае TransactionsStore имеет смысл, потому что данный сервис будет хранить все текущие транзакции.

Теперь нам необходимо соединить этот сервис с TransactionsCtrl. В Angular.js используется паттерн Dependency Injection. Фреймворк умеет сам разрешать необходимые зависимости, разработчику необходимо только указать название компонента, который нужен другому компоненту приложения. Выглядит указание зависимостей следующим образом:

// src/app/main/transactions.controller.js
angular.module('ngmkdev').controller('TransactionsCtrl', function($scope, TransactionsStore) {
  // ...
});

Теперь у нас есть доступ к нашему сервису из контроллера для транзакций. Так как мы использовали factory, то при вызове TransactionsStore будет вызвана функция из определения этого сервиса, а значит мы можем легко получить все транзакции и записать их атрибуты контроллера следующим образом:

// src/app/main/transactions.controller.js
angular.module('ngmkdev').controller('TransactionsCtrl', function($scope, TransactionsStore) {
  this.transactions = TransactionsStore.transactions;
  // ...
});

Обратите внимание, что остальная часть кода остаётся неизменной – Angular.js сам позаботится о связи атрибута контроллера transactions и обновлением сервиса.

Теперь убедимся в работоспособности нашего сервиса. Проделаем ряд уже знакомых операций:

Добавим новый контроллер src/app/main/navigation.controller.js, отвечающий за боковое меню в приложении:

// src/app/main/navigation.controller.js
angular.module('ngmkdev').controller('NavigationCtrl', function(TransactionsStore) {
  this.transactions = TransactionsStore.transactions;
});

Определим его на боковом меню и выведем число транзакции в скобках после пункта Транзакции:

<!-- src/index.html -->

<!-- ... -->
<div class="col-xs-2" ng-controller="NavigationCtrl as navigation_ctrl">
  <h2>Деньги</h2>
  <h3 class="money-ok">
    500.0
  </h3>
  <ul class="nav nav-pills nav-stacked">
    <li>
      <a href="#">
        <i class="glyphicon glyphicon-th-list"></i>
        Транзакции <span class="badge">{{navigation_ctrl.transactions.length}}</span>
      </a>
    </li>
    <li>
      <a href="#"><i class="glyphicon glyphicon-tasks"></i> Настройки</a>
    </li>
  </ul>
</div>
<!-- ... -->

Перезагрузим страницу в браузере (если gulp ещё не сделал этого) и попробуем добавить транзакцию. Помимо обновления таблицы с транзакциями автоматически обновляется и счётчик транзакций в боковом меню.

Коммит со всеми изменениями, как всегда, в репозитории проекта на GitHub: 6d661c0

Домашняя работа (подсказки):

  1. Замените статичную сумму транзакций в боковом меню на настоящую.
  2. Спрячьте таблицу если у пользователя нет ни одной транзакции