Save 37% off PRO during our Black Friday Sale! »

ngPittsburgh - AngularUI Router Philosophy

7fca546408cc6d46ab158f06baed2535?s=47 Nate Abele
September 16, 2015

ngPittsburgh - AngularUI Router Philosophy

Talk given at ngPittsburgh on September 16th, 2015 about the philosophy and future of AngularUI Router.

7fca546408cc6d46ab158f06baed2535?s=128

Nate Abele

September 16, 2015
Tweet

Transcript

  1. AngularUI Router Why, and What’s Next? ngPittsburgh · Sept 2015

  2. Basically a Vanity Slide Former lead dev, CakePHP Founder, Li3

    (aka Lithium) Member, AngularUI Team Founding Member / Lead Dev, UI Router Architect, Radify @nateabele nate@radify.io
  3. radify.io · @radify Software Architecture Open Source Strategy · ·

    Training Recruiting &
  4. AngularUI What?

  5. AngularUI What? AngularUI Router is a state machine that coordinates

    user interface rendering, data flow, and URL synchronization, as a user navigates through a system.
  6. State Machine? “[A] mathematical model of computation used to design

    both computer programs and sequential logic circuits. It is conceived as an abstract machine that can be in one of a finite number of states.” — Wikipedia: Finite-state machine
  7. “The main reason for using state machines is to help

    the design process. It is much easier to figure out all the possible edge conditions by drawing out the state machine on paper. This will make sure that your application will have less bugs and less undefined behavior.” State Machine?
  8. “Moreover, state machines have decades of math and CS research

    behind them about analyzing them, simplifying them, and much more. Once you realize that in management state machines are called business processes, you'll find a wealth of information and tools at your disposal.” https://www.shopify.com/technology/3383012-why-developers-should-be-force-fed-state-machines State Machine?
  9. State Machine? Turnstile

  10. State Machine? Light Switch

  11. State Machine? Transmission

  12. State Machine? E-Commerce System

  13. “Make Illegal States Unrepresentable”

  14. In the beginning…

  15. /users/:id/view /users/:id /users

  16. None
  17. None
  18. Enter Component Router

  19. Component Router Nested routes Nested components Navigation pipeline with lifecycle

    hooks
  20. Lifecycle Hooks canActivate activate canDeactivate deactivate

  21. Component Router $router.config([ { path: '/', redirectTo: '/home' }, {

    path: '/home', component: 'home' }, { path: '/users', component: 'users' } ]);
  22. Declarative Programming $(document).ready(function() { $('#name').keydown(function(e) { $('h1').html("Hello " + e.target.value)

    }); }); <input type="text" id="name" /> <h1>Hello [Name]!</h1> +
  23. Declarative Programming vs.

  24. Declarative Programming <input type="text" ng-model=“person.name" /> <h1>Hello {{person.name}}!</h1>

  25. So what’s new?

  26. $rootScope.$on(“$stateChange*”)

  27. $rootScope.$on('$stateChangeStart', (e, toState) => { if (toState.data.authorization && !user.isLoggedIn()) {

    e.preventDefault(); $state.go("login"); } if (toState.data.admin && !user.isAdmin()) { // ... } // ... });
  28. $transitionsProvider.onStart({ from: "*" to: “user.*” }, user => user.ensureLogin().then(() =>

    true));
  29. $transitionsProvider.onStart({ from: "*" to: “user.*” }, user => user.ensureLogin().then(() =>

    true));
  30. $transitionsProvider.onStart({ to: state => !!state.data.requiresAuth }, user => user.ensureLogin().then(() =>

    true));
  31. $transitionsProvider.onStart({ to: state => !!state.data.requiresAuth }, user => user.ensureLogin().then(() =>

    true));
  32. Hook Values true: transition allowed false: transition rejected { …

    }: new resolve values Promise<*>: Any value can be promise-wrapped
  33. $transitionsProvider.onStart({ to: state => !!state.data.requiresAuth }, user => user.ensureLogin().then(() =>

    true));
  34. $transitionsProvider.onStart({ to: state => !!state.data.requiresAuth }, (user, $state, $transition$) =>

    { return ( user.isLoggedIn() || $state.redirect($transition$).to('user.login') ); });
  35. The Transition Object $transition.to(): the target state $transition.from(): the origin

    state $transition.params(): target state parameters $transition.options(): passed transition options
  36. The Transition Object $transition.entering(): states being entered $transition.exiting(): states being

    exited $transition.retained(): states retained $transition.views(): view configs for changed states
  37. The Transition Object $transition.resolves(): resolve values Planned:

  38. Hooks onBefore onStart onFinish onSuccess onError Per Transition onEnter onRetain

    onExit Per State
  39. Types

  40. url: "/maps/{location:crazy-regex}"

  41. url: "/maps/{location:Location}"

  42. export default class Location { constructor( public lat: number, public

    lon: number, public zoom: number ) {} toString() { return [this.lat, this.lon, this.zoom].join(",") + "z" } }
  43. $urlMatcherFactoryProvider.type("Location", { encode(loc) { return “@" + loc; } decode(str)

    { return new Location( ...str.match(this.pattern).slice(1) ); }, pattern: /@(-?\d+\.\d+),(-?\d+\.\d+),(\d+)z/ });
  44. $stateProvider.state("map", { url: "/map/{location:Location}", params: { location: { dynamic: true

    } } });
  45. class MapController { constructor($scope, $stateParams) { // Expose for binding

    to maps directive $scope.location = $stateParams.location; // Changes to map will auto-propagate to URL $stateParams.$observe("location", () => { ... }) } }
  46. Bonus Round TypeScript Trace service Composable builders Resolve policies