ui-routerを読み直し
(1年前にまとめたもの。こっちに転載。最新のUI-Routerについては Angular UI-Router v1さわる - ryotah’s blog から)
動機
- ui-router のこと、実はあまり把握していなかった
- Nested States & Views とか Multiple & Named Views とか一応使っているけどあんまりよくわかっていない
- ひとまず angular-ui/ui-router Wiki に目を通すか ← イマココ
書いてあること
- 仕事で利用したTips
- angular-ui/ui-router Wiki の以下ページから、役立ちそうなものと面白そうなもの抜粋
仕事で利用したTips
遷移時にデータを渡したい
- How to pass custom data in $state.go() in angular-ui-router? · Issue #1949 · angular-ui/ui-router
- stateConfig の params を利用する
- additional non-url parameters を定義できる
// foo.ts $stateProvider .state('foo', { url: '/foo', template: '<foo></foo>', params: { // non-url parameter data: null, } }) // bar.controller.ts go() { this.$state.go('foo', { data: { // ... }, }); }
動的にtemplateUrlを変更したい
$templateProvider
を使う
$stateProvider .state('foo', { url: 'foo', controller: 'FooController', /*@ngInject*/ templateProvider: function($templateFactory, BarService) { return $templateFactory.fromConfig({ templateUrl: BarService.getBool() ? 'a.html' : 'b.html' }); } });
履歴、location bar のコントロール
location - {boolean=true|string=} - If true will update the url in the location bar, if false will not. If string, must be “replace”, which will update url and also replace last history record.
- http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state
- urlを変えたい、履歴も変えたい (true)
- 何も変更したくない (false)
- urlを変えたいが、遷移したことを履歴に残したくない (replace)
遷移先を途中で変更する
$stateProvider.state の resolve 内で遷移先を変更する
resolve: { /*@ngInject*/ data: function($stateParams, $state, $q, $timeout) { const data = $stateParams.data; if (data) { return "something"; } // go to xxx if no data $timeout(() => { $state.go("xxx"); }, 0); return $q.defer('error message'); } }
副作用なく、location barのクエリだけを変更したい
$state.go('.', { query: "query" }, { notify: false });
- $stateChangeStart と $stateChangeSuccess events を broadcast しない
ui-sref, ui-sref-active
- ui-sref - You just need to be aware that the path is relative to the state that the link lives in
- ui-sref-active
- A directive working alongside ui-sref to add classes to an element when the related ui-sref directive’s state is active
State Manager
- Resolve
- onEnter and onExit callbacks
Nested States and Nested Views
Nested Statesの設定
Dot Notationによる設定
$stateProvider .state('contacts', {}) .state('contacts.list', {});
<a ui-sref="contacts">Go Contacts</a> <a ui-sref="contacts.list">Go Contacts List</a>
Parent Propertyによる設定
$stateProvider .state('contacts', {}) .state('list', { parent: 'contacts' });
<a ui-sref="contacts">Go Contacts</a> <!-- "contacts.list" にはならない --> <a ui-sref="list">Go Contacts List</a>
stateに設定している名称は違うが、両方とも contacts(親)、list(子)の関係になっている。 このへんちょっとややこしい。
親Statesから引き継げるもの
Abstract States
子Stateを持つことができるが遷移できないState。
利用例として考えられるもの:
- urlを子Stateに追加したい場合
- ui-viewを含むtemplateを子Stateで利用したい場合
- Resolved dependencies via
resolve
を子Stateで利用したい場合 - Custom data properties via
data
を子Stateで利用したい場合 - To run an onEnter or onExit function that may modify the application in someway.
Multiple Named Views
Absolute Names
viewname@statename
の形式を利用すると ui-view を絶対名で指定できる。
例えば、Nested States だけど Views を入れ子にしたくない場合、以下のような書き方が可能。
<div ng-app="ngapp"> <div ui-view></div> <div ui-view="list"></div> </div>
$stateProvider .state('state1', { url: '/state1', template: 'state1' }) .state('state1.list', { url: '/list', views: { // このケースのように State がルートの場合、@の後ろには何もかかない 'list@': { template: 'state2' } } });
URL Routing
- Basic Parameters
/user/:id
,/user/{id}
,/user/{id:int}
- Query Parameters
/contacts?myParam1&myParam2
- Absolute Routes
url: '^/list'
のようにすると、Nested State でも Url は結合されない
$stateParams
は親Stateのパラメーターなどは取得できない(自分自身のパラメーターのみ取得可能)- 親Stateで resolve すれば取得可能
$stateProvider.state('contacts.detail', { url: '/contacts/:contactId', controller: function($stateParams){ $stateParams.contactId //*** Exists! ***// }, resolve:{ contactId: ['$stateParams', function($stateParams){ return $stateParams.contactId; }] } }).state('contacts.detail.subitem', { url: '/item/:itemId', controller: function($stateParams, contactId){ contactId //*** Exists! ***// $stateParams.itemId //*** Exists! ***// } })