Роутинг в Angular.js
Мы подходим к концу нашего руководства по Angular.js. Осталось всего две статьи: эта и ещё одна. В этой мы рассмотрим Angular.js UI Router – библиотеку для организации навигации между различными частями нашего приложения. Заодно мы перепишем наш код так, чтобы он использовал шаблоны, вместо хранения всего html в одном файле.
Шаблоны в нашем приложении хранятся в папке src/app/app_part/
. Под app_part
я имею ввиду отдельную часть приложения. Сейчасу нас только main
, но в будущем могут быть так же подпапки settings
, categories
и что угодно ещё. Перенесём всю центральную часть, содержащую форму для добавления транзакций и таблицу с транзакциями в src/app/main/transactions.html и заменим её на:
<div class="col-xs-6" ui-view></div>
Так же необходимо убрать ui-view из контейнера уровнем выше. Таким образом в src/index.html
внутри тега body помимо тегов script у нас остаётся следующая вёрстка:
<div class="container">
<div class="col-xs-2" ng-controller="NavigationCtrl as navigation_ctrl">
<h2>Деньги</h2>
<h3 class="money-ok">
{{navigation_ctrl.transactions_store.sum()}}
</h3>
<ul class="nav nav-pills nav-stacked">
<li>
<a>
<i class="glyphicon glyphicon-th-list"></i>
Транзакции <span class="badge">{{navigation_ctrl.transctions_store.transactions.length}}</span>
</a>
</li>
<li>
<a>
<i class="glyphicon glyphicon-tasks"></i> Настройки
</a>
</li>
</ul>
</div>
<div class="col-xs-6" ui-view></div>
</div>
Теперь у нас ничего не работает, потому что мы не указали UI Router’у какой шаблон выводить в ui-view по корневой ссылке. Именно этим данная библиотека и занимается: вставляет в ui-view шаблон, соответствующий настройкам приложения.
Итак, обновим src/app/index.js
:
'use strict';
angular.module('ngmkdev', ['restangular', 'ui.router'])
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('transactions', {
url: "/",
templateUrl: "app/main/transactions.html"
});
$urlRouterProvider.otherwise('/');
});
Мы используем функцию config()
для конфигурации различных провайдеров (один из видов сервисов) до того как они начнут использоваться в других частях приложения.
Здесь через цепочку вызовов функции state()
на сервисе $stateProvider
мы указываем какой шаблон выводить внутри ui-view для каждой страницы. Последняя строчка, $urlRouterProvider.otherwise('/');
говорит Angular’у на какой адрес перенаправлять пользователя если запрошенный маршрут не существует. Наше приложение теперь снова должно работать как и прежде.
Немного аналогий для знакомых с Ruby on Rails: ui-view можно сравнить с yield в рельсовых шаблонах, а цепочку вызовов
state()
– с файлом routes.rb.
Попробуем добавить настоящую навигацию: чтобы ссылка Транзакции вела на таблицу с транзакциями, а Настройки на будущую страницу настроек пользователя.
Обновим наш список маршрутов:
'use strict';
angular.module('ngmkdev', ['restangular', 'ui.router'])
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('transactions', {
url: "/transactions",
templateUrl: "app/main/transactions.html"
})
.state('settings', {
url: "/settings",
templateUrl: "app/settings/settings.html"
})
$urlRouterProvider.otherwise('/transactions');
});
И добавим файл app/settings/settings.html
с таким содержанием:
<h2>Настройки</h2>
Теперь на любой несуществующий путь будет происходить редирект на страницу с транзакциями. Попробуйте открыть следующие пути: http://localhost:3000/
, http://localhost:3000/#/transactions
, http://localhost:3000/#/settings
, http://localhost:3000/#/crap
.
Толку от ручного вбивания адресов немного, поэтому оживим ссылки в боковом меню. Для этого в UI Router существует директива ui-sref
, в которой указывается название стейта (первый аргумент функции state()), который должен открыться по клику на ссылке:
<li>
<a ui-sref="transactions">
<i class="glyphicon glyphicon-th-list"></i>
Транзакции <span class="badge">{{navigation_ctrl.transctions_store.transactions.length}}</span>
</a>
</li>
<li>
<a ui-sref="settings">
<i class="glyphicon glyphicon-tasks"></i> Настройки
</a>
</li>
Этого достаточно чтобы наше меню заработало – по клику на ссылки центральная часть приложения меняется. Коммит с изменениями, проделанными в статье: 448daee.
Задание на дом:
- Найдите в документации UI Router способ подсвечивать текущий пункт меню