angular js routing

18
AngularJS Application Routing Tuesday, 13 August 13

Upload: kennystoltz

Post on 03-Jul-2015

4.834 views

Category:

Business


2 download

DESCRIPTION

Talk given at AngularJS meeting in London on 13 August 2013.

TRANSCRIPT

Page 1: Angular JS Routing

AngularJS Application Routing

Tuesday, 13 August 13

Page 2: Angular JS Routing

Routes: REST/Servers v. Client Apps

•HTTP is stateless, so routes help define application state. •REST emphasizes semantic routes. (GET  /user/dave)

But...•There is more state than can be represented in a route (user state, session state)•Client-side apps don’t actually need routes to work (e.g. many jquery-based apps)

Tuesday, 13 August 13

Page 3: Angular JS Routing

Why use routes?

Routes:• Make the back button work as expected• Make major (page-like) transitions clear• Allow easy linking• Make testing easier• Encapsulate some state

Tuesday, 13 August 13

Page 4: Angular JS Routing

From Angular-Phonecat:

angular.module('phonecat',  ['phonecatFilters',  'phonecatServices']).    config(['$routeProvider',  function($routeProvider)  {    $routeProvider.

           when('/phones',  {templateUrl:  'partials/phone-­‐list.html',      controller:  PhoneListCtrl}).

           when('/phones/:phoneId',  {templateUrl:  'partials/phone-­‐detail.html',  controller:  PhoneDetailCtrl}).

           otherwise({redirectTo:  '/phones'});}]);

Basic Routes

Tuesday, 13 August 13

Page 5: Angular JS Routing

.when('/phones/:phoneId',  {templateUrl:  'partials/phone-­‐detail.html',  controller:  PhoneDetailCtrl})

:phoneId stored in $route.current.params, available controller and resolve functions.

Basic Routes

Tuesday, 13 August 13

Page 6: Angular JS Routing

Realistic Routes Structure/ – welcome/stream – logged-in home/login – log-in/signup – signup/user/:username – user profile /explore – explore tags/settings – user settings/new-spark – create spark page/spark/cluster?sparkName=&tagName – spark cluster page/search – search/spark/:username/:slug – spark page...and 11 more routes

Tuesday, 13 August 13

Page 7: Angular JS Routing

Resolve for DataEach item in the resolve map:

•Runs before the controller is instantiated•Provides its value to the controller•If it is a promise:

•It will (wait to) resolve the promise first•If the promise is rejected, the route errors

Using resolve for database objects means•No UI flicker as promises are resolved•Controllers can assume objects exist•Tests are cleaner: pass in data object explicitly

Tuesday, 13 August 13

Page 8: Angular JS Routing

Resolve for Data

when('/tag/:tagName',  {  resolve:  {    tagResolve:  ['tag','$route',      function  (tagService,  $route)  {        return  tagService.get($route.current.params.tagName);    }],    sparkClustersResolve:  ['sparkCluster','$route',      function  (sparkClusterService,  $route)  {        return  sparkClusterService.getSparkClustersByTag($route.current.params.tagName);}]}});

Tuesday, 13 August 13

Page 9: Angular JS Routing

Resolve for Data

Treat your resolved object like a dependency in the controller:.controller('ViewTagCtrl',  ['$scope','$routeParams','tag','sparkCluster','log','$location','user','header','sparkClustersResolve','tagResolve','currentUserResolve'

Use a ‘route controller’, not a ‘view controller’ (ng-­‐controller):when('/tag/:tagName',  {  controller:  'ViewTagCtrl'  })

Tuesday, 13 August 13

Page 10: Angular JS Routing

Resolve for RulesRejected Promises cause routes to fail. You can use this to make rules for the route like ACLs or prerequisites. Reject a promise to cause a route to fail.

Using resolve to make rules means:•All resolution rules must pass before route succeeds and controller is instantiated. •Common ACLs (logged-in) specified in routes, not each controller or service•Can redirect the user to an appropriate page (also can do user-facing error)

Tuesday, 13 August 13

Page 11: Angular JS Routing

when('/tag/:tagName',  {  resolve:  {    mustAuth  :  ['route',  function  (routeService)  {        return  routeService.mustAuth('/');}]}]}});

routeService.mustAuth  =  function  (redirectTo)  {  var  authDeferred,  p;  authDeferred  =  $q.defer();  p  =  userService.getCurrent();  p.then(function  (currentUser)  {    if  (angular.isUndefined(currentUser._id))  {      $location.url(redirectTo);      authDeferred.reject();    }  else  {  authDeferred.resolve(mustAuth);  }});  return  authDeferred.promise;};

Resolve for Rules

Tuesday, 13 August 13

Page 12: Angular JS Routing

Resolve for Route-Specific UI

Resolve can pass route-specific configuration to another service that a"ects the UI, like “show a promo”.

Using resolve to control UI means:•Routes handle turning on and o" UI elements•Route Controllers don’t need to worry about configuring site-wide UI elements like headers, promos, menus

*There are other (possibly better) options for this, including having the UI controller listen to RouteChangeSuccess events.

Tuesday, 13 August 13

Page 13: Angular JS Routing

when('/tag/:tagName',  {  resolve:  {    makeSparkPromo:  ['promo',      function  (promoService)  {        return  promoService.route('makeSparkPromo',  true);}]}}});

Resolve for Route-Specific UI

Tuesday, 13 August 13

Page 15: Angular JS Routing

ROUTER.when('tag',  '/tag/:tagName',  {  templateUrl:  '/partials/tag/tag-­‐detail.html',  controller:  'ViewTagCtrl'});

ROUTER.otherwise({  redirectTo  :  '/'});

ROUTER.install($routeProvider);

Testing Routes Midway–Router Helper

Tuesday, 13 August 13

Page 16: Angular JS Routing

before(function(done)  {  test  =  new  ngMidwayTester();  test.register('App',  done);});

it('should  have  a  route  to  a  tag  page',  function()  {        expect(  ROUTER.routeDefined('tags')).to.equal(true);  var  url  =  ROUTER.routePath('tags',  {tagName:  ‘cooking’);  expect(url).to.equal('/tag/cooking');});

Testing Routes Midway–Testing

Tuesday, 13 August 13

Page 17: Angular JS Routing

Recap

The phonecat way (sticking everything under app) is unscalable.

Angular’s route system is flexible and powerful, if you take advantage of resolve and promises.

Using helper functions and midway testing means you can unit test more things. The less you rely on E2E testing, the better.

Tuesday, 13 August 13

Page 18: Angular JS Routing

Other Good Ideas

Others have addressed the same problems in a more reusable way.

Angular UI router: use ‘state’ instead of routes. Seems good. Worth considering if you start fresh.

Angular App: great example of well-designed app, but maybe hard to follow for a novice. Interesting crudRouteProvider implementation.

Tuesday, 13 August 13