View
1.884
Download
0
Category
Preview:
DESCRIPTION
My talk on uiRouter from the October ngNYC meetup. http://www.meetup.com/ng-nyc
Citation preview
ARCHITECTURE, AUTH, AND ROUTING WITH UIROUTER
chris caplinger
ccaplinger@neosavvy.com
@unicode_snowman
WHAT IS UIROUTER?“AngularUI Router is a routing framework forAngularJS, which allows you to organize theparts of your interface into a state machine.
Unlike the $route service in the Angular ngRoutemodule, which is organized around URL routes,
UI-Router is organized around states, which mayoptionally be associated with URLs.”
WHY A ROUTER IN GENERAL?Associates Routes/URLs with application state
i.e. views and their associated controllers and models
“When we wrote the original router it was, to ourimagination, pretty cool... except it was vastlyinadequate for a large number of use cases.”
NGROUTE SHORTCOMINGSonly one ngViewencourages ngShow/ngHide/ngIf/ngSwitch abusenested templates in nested templates in nested templates... in nested templates...
...overall, painful with larger apps
SO WHAT'S DIFFERENT ABOUT UIROUTER?
STATE STATE STATE“...an abstract machine that can be in one of afinite number of states. The machine is in onlyone state at a time... It can transition from one
state to another by a triggering event orcondition; A particular FSM is defined by a list of
its states, and the triggering condition for eachtransition.”
YOUR APP IS ALREADY STATEFUL!
angular.module('MyApp').config(function ($stateProvider) { $stateProvider .state({ name: 'home', url: '/', templateUrl: '/where/is/my/home/template-ptl.html', controller: 'HomeController', resolve: { /* get some data! */ } }) .state({ name: 'items', url: '/items', templateUrl: '/where/is/my/template-ptl.html', controller: 'ItemsController', resolve: { items: function (Item) { return Item.all(); } } });});<!-- somewhere else, likely index.html --><ui-view></ui-view>
$STATE// navigate to /home state$state.go('home')
// navigate to /items state$state.go('items')
<a ui-sref="items">Check Out These Items</a>
NESTED VIEWS$stateProvider .state({ name: 'items', url: '/items', // navigate to /items templateUrl: '/my/item/template-ptl.html', }) .state({ name: 'items.detail', url: '/:id', // navigate to /items/123 because items.detail is a child state of items templateUrl: 'my/item/detail/template-ptl.html', controller: 'ItemController', resolve: { item: function (Items, $stateParams) { return Items.find($stateParams.id); } } });
<!-- index.html --><ui-view></ui-view>
<!-- my/item/template-ptl.html --><ui-view></ui-view>
// get there with...$state.go('items.detail', { id: 123 });
// or relative...$state.go('.detail', { id: 123 });
<!-- or via a link... --><a ui-sref=".detail({ id: 123 })">Item 123</a>
DEMO TIMESTEP-BY-STEP FLOW!
NAMED VIEWS
$stateProvider .state({ name: 'someParent', url: '/parent', views: { 'layoutA': { templateUrl: '/layout-a.html' }, 'content1@someParent': { templateUrl: 'content-1.html' }, 'content2@someParent': { templateUrl: 'content-2A.html' } } }) .state({ name: 'someParent.child', url: '/:id', views: { 'content2@someParent': { templateUrl: 'content-2B.html' } } });
<!-- index.html --><ui-view name="layoutA"></ui-view>
<!-- layout-a.html --><div> <ui-view name="content1"></ui-view></div><div> <ui-view name="content2"></ui-view></div>
THE RETURN OF DEMOTIME
NAMED VIEWS!
AUTHORIZATION AND REDIRECTION
OBLIGATORY OBVIOUSTHING
CLIENT-SIDE AUTH AIN'T NO THINGserver side is where the magic happens
this is really about UX
$STATECHANGE* EVENTSangular.app('MyApp').run(function ($rootScope, $state) { $rootScope.$on('$stateChangeError', function (e, toState, toParams, fromState, fromParams, error) if (error.status == 401) { $state.go('login'); } else { // other error types, 404, 500 // maybe a redirect, maybe not } });});
angular.app('MyApp').run(function ($rootScope, $state, AuthService, User) { $rootScope.$on('$stateChangeStart', function (e, toState, toParams, fromState, fromParams, error) { if (toState.data.checkAuth && !User.isAuthorized) { e.preventDefault();
AuthService.doAsyncThing().then(function (res) { $state.go(toState, toParams, { notify: false }).then(function () { $rootScope.$broadcast('$stateChangeSuccess', toState, toParams, fromState }); }).catch(function (err) { // do something here, redirect, or let your $stateChangeError handler catch the error }) } });});
OTHER THOUGHTS ON REDIRECTIONdecorate $state.transitionTo for finer-grained control (a bit
hackier than I'd like, but it works)$stateChangeError redirection from navigating directly to a
URL, need to replace entry
QUESTIONS, COMMENTS, CONCERNS?
chris caplinger
ccaplinger@neosavvy.com
@unicode_snowman
Recommended