Designing Front-end Architectures with AngularUI Router

Introductories

Hi!

<plug disposition="shameless" />

Hypermedia APIs + front-end architectures with AngularJS

Thanks!

  • Amazingly, I get paid for this stuff
  • OS is magical because of people
  • I'm not a peasant

Life Lessons

  • Be humble
  • Don't be afraid to feel stupid
  • The night is young

3 things

  • Hypermedia & the browser as an app platform

  • UI-Router architecture

  • Application design

Problem-solving context

UI === app (SPA++)

Hypermedia?

Hypermedia


  • REST: endpoints, methods, the usual
  • Content type: no special knowledge
  • State machine: you can get there from here

Dueling state machines?

Resource state
vs.
Client state

Entré the Memento pattern

  • Formerly, 'client state' would be the browser itself
  • Now, the browser application traverses resources directly

UI-Router

  • Nested states
  • Nested views
  • Hierarchical URL routes
  • Animated transitions

ngRoute?


  • No nesting
  • (URL === view) is a bad abstraction

$stateProvider.state("myState", {
  controller: "MyStateController",
  templateUrl: "/templates/my-state.html",
  // or views: { ... }
  /* ... */
});

$stateProvider.state("myState", {
  /* ... */
  onEnter: function($stateParams, MyService) { /* ... */ }
  onExit: function($stateParams, MyService) { /* ... */ },
  resolve: {
    dynamicData: function($stateParams, OtherService) {
      return OtherService.loadAThing(); // promise
    }
  }
});

Application design

Application design

  • Slice mockups into views
  • Organize into states
  • Map parameters to domain objects
url: "/maps/{location:crazy-regex}"
url: "/maps/{location:Location}"

$urlMatcherFactoryProvider.type("Location", {
  encode: function (loc) {
    return "@" + [loc.lat, loc.lon, loc.zoom].join(",") + "z";
  },
  decode: function (string) {
    var val = this.pattern.exec(string);
    return { lat: val[1], lon: val[2], zoom: val[3] };
  },
  pattern: /imagination-here/
});

$stateProvider.state("map", {
  url: "/map/{location:Location}",
  params: {
    location: { dynamic: true }
  }
});

function MapController($scope, $stateParams) {
  // Expose for binding to maps directive
  $scope.location = $stateParams.location;
  // Changes to map will auto-propagate to URL
}

Pro tip

Enter / exit hooks should be idempotent

Bonus pro tip

It's prototypal, not prototypical

[Insert App Demo Here]

Questions?

Thanks/Contact