<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <base href="." />
    <script src="https://code.angularjs.org/tools/system.js"></script>
    <script src="https://code.angularjs.org/tools/typescript.js"></script>
    <script src="config.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.9/angular2-polyfills.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.9/Rx.min.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.9/angular2.dev.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.9/router.dev.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.9/http.dev.js"></script>
    <script>
      System.import('app')
        .catch(console.error.bind(console));
    </script>
  </head>

  <body>
    <app>Loading....</app>
  </body>

</html>
//main entry point
import {bootstrap} from 'angular2/platform/browser';
import {provide} from 'angular2/core';
import {ROUTER_PROVIDERS} from 'angular2/router';
import {App} from './app';
import {Resolved} from './util';
import 'rxjs/Rx';
import {RouterResolve} from './RouterResolve';
import {HTTP_PROVIDERS} from 'angular2/http';
import {appInjector} from './app-injector';
import {UserService, Users} from './Users';

bootstrap(App, [
  ROUTER_PROVIDERS,
  HTTP_PROVIDERS,
  RouterResolve,
  UserService,
  provide(Users, {useValue: []})
]).then((appRef: ComponentRef) => {
  appInjector(appRef.injector);
});
//our root app component
import {Component, OpaqueToken, Injector} from 'angular2/core';
import {RouterLink, Route, RouteConfig} from 'angular2/router';
import {Home} from './Home';
import {Resolve} from './Resolve';
import {RouterOutlet} from './RouterOutlet';

@Component({
  selector: 'app',
  template: `
    <a [routerLink]="['Home']">Home</a> | 
    <a [routerLink]="['Resolve']">Resolve Users</a>
    <hr>
    <router-outlet></router-outlet>
  `,
  directives: [RouterLink, RouterOutlet]
})
@RouteConfig([
  new Route({path: '/', component: Home, name: 'Home'}),
  new Route({path: '/resolve', component: Resolve, name: 'Resolve'})
])
export class App {}
import {Component, Inject, provide} from 'angular2/core';
import {CanActivate} from 'angular2/router';
import {Resolved} from './util';

@Component({
  selector: 'home',
  template: `
    Welcome Home
  `
})

export class Home {}
System.config({
  //use typescript for compilation
  transpiler: 'typescript',
  //typescript compiler options
  typescriptOptions: {
    emitDecoratorMetadata: true
  },
  //map tells the System loader where to look for things
  map: {
    app: "./src"
  },
  //packages defines our app package
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    }
  }
});
import {Component, provide, Inject, Injector} from 'angular2/core';
import {CanActivate, Router} from 'angular2/router';
import {Http} from 'angular2/http';
import {Users, UserService} from './Users';
import {RouterResolve} from './RouterResolve';
import {appInjector} from './app-injector';

@Component({
  selector: 'resolve',
  template: `
    Users retrieved: {{ users.length }}
  `
})
@CanActivate((next: ComponentInstruction, prev: ComponentInstruction) => {
  let injector:Injector = appInjector();
  let routerResolve:RouterResolve = injector.get(RouterResolve);
  let userService:UserService = injector.get(UserService);
  
  return userService.getUsers()
        .toPromise()
        .then((users) => {
          routerResolve.setProviders(next, [
            provide(Users, {useValue: users})
          ]);
          
          // continue
          return true;
        }).catch(() => {
          // stop
          return false;
        });
})
export class Resolve {
  constructor(public users: Users) {}
}
import {Directive, Attribute, ElementRef, DynamicComponentLoader, Injector, provide} from 'angular2/core';
import {Router, RouterOutlet as NgRouterOutlet, ComponentInstruction, RouteParams, RouteData} from 'angular2/router';
import * as hookMod from 'angular2/src/router/lifecycle/lifecycle_annotations';
import {hasLifecycleHook} from 'angular2/src/router/lifecycle/route_lifecycle_reflector';
import {RouterResolve} from './RouterResolve';

@Directive({selector: 'router-outlet'})
export class RouterOutlet extends NgRouterOutlet {
  constructor(
    private _elementRef: ElementRef,
    private _loader: DynamicComponentLoader,
    private _parentRouter: Router,
    @Attribute('name') nameAttr: string,
    private _routerResolve: RouterResolve
  ) {
     super(_elementRef, _loader, _parentRouter, nameAttr);
  }
  
  activate(nextInstruction: ComponentInstruction): Promise<any> {
    let previousInstruction = this._currentInstruction;
    this._currentInstruction = nextInstruction;
    let componentType = nextInstruction.componentType;
    let childRouter = this._parentRouter.childRouter(componentType);

    let providers = Injector.resolve([
      provide(RouteData, {useValue: nextInstruction.routeData}),
      provide(RouteParams, {useValue: new RouteParams(nextInstruction.params)}),
      provide(Router, {useValue: childRouter}),
      ...(this._routerResolve.getProviders(nextInstruction) || [])
    ]);
    
    return this._loader.loadNextToLocation(componentType, this._elementRef, providers)
        .then((componentRef) => {
          this._componentRef = componentRef;
          if (hasLifecycleHook(hookMod.routerOnActivate, componentType)) {
            return (<OnActivate>this._componentRef.instance)
                .routerOnActivate(nextInstruction, previousInstruction);
          }
        });
  }  
}
import {Injectable} from 'angular2/core';
import {ComponentInstruction} from 'angular2/router';

@Injectable()
export class RouterResolve {
  private providers = new Map<ComponentInstruction, any>();
  
  setProviders(ins: ComponentInstruction, providers: any[] = []) {
    this.providers.set(ins, providers);
  }
  
  getProviders(ins: ComponentInstruction) {
    return this.providers.get(ins) || [];
  }
}
import {Injector} from 'angular2/core';

let appInjectorRef: Injector;
export const appInjector = (injector?: Injector): Injector => {
	if (injector) {
		appInjectorRef = injector;
	}

	return appInjectorRef;
};
import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';

export class Users {}

@Injectable()
export class UserService {
  constructor(public http: Http) {}
  
  getUsers() {
    return this.http.get('http://api.randomuser.me/?nat=us&results=25')
      .map((res) => res.json())
      .map((res) => res.results)
      .map((res) => res.map(item => item.user));
  }
}