Architecture, Auth, and Routing with uiRouter

  • View
    1.884

  • Download
    0

  • Category

    Software

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