diff --git a/modules/@angular/examples/router/ts/.gitkeep b/modules/@angular/examples/router_deprecated/ts/.gitkeep
similarity index 100%
rename from modules/@angular/examples/router/ts/.gitkeep
rename to modules/@angular/examples/router_deprecated/ts/.gitkeep
diff --git a/modules/@angular/examples/router/ts/can_activate/can_activate_example.ts b/modules/@angular/examples/router_deprecated/ts/can_activate/can_activate_example.ts
similarity index 100%
rename from modules/@angular/examples/router/ts/can_activate/can_activate_example.ts
rename to modules/@angular/examples/router_deprecated/ts/can_activate/can_activate_example.ts
diff --git a/modules/@angular/examples/router/ts/can_activate/can_activate_spec.ts b/modules/@angular/examples/router_deprecated/ts/can_activate/can_activate_spec.ts
similarity index 100%
rename from modules/@angular/examples/router/ts/can_activate/can_activate_spec.ts
rename to modules/@angular/examples/router_deprecated/ts/can_activate/can_activate_spec.ts
diff --git a/modules/@angular/examples/router/ts/can_activate/index.html b/modules/@angular/examples/router_deprecated/ts/can_activate/index.html
similarity index 100%
rename from modules/@angular/examples/router/ts/can_activate/index.html
rename to modules/@angular/examples/router_deprecated/ts/can_activate/index.html
diff --git a/modules/@angular/examples/router/ts/can_deactivate/can_deactivate_example.ts b/modules/@angular/examples/router_deprecated/ts/can_deactivate/can_deactivate_example.ts
similarity index 100%
rename from modules/@angular/examples/router/ts/can_deactivate/can_deactivate_example.ts
rename to modules/@angular/examples/router_deprecated/ts/can_deactivate/can_deactivate_example.ts
diff --git a/modules/@angular/examples/router/ts/can_deactivate/can_deactivate_spec.ts b/modules/@angular/examples/router_deprecated/ts/can_deactivate/can_deactivate_spec.ts
similarity index 100%
rename from modules/@angular/examples/router/ts/can_deactivate/can_deactivate_spec.ts
rename to modules/@angular/examples/router_deprecated/ts/can_deactivate/can_deactivate_spec.ts
diff --git a/modules/@angular/examples/router/ts/can_deactivate/index.html b/modules/@angular/examples/router_deprecated/ts/can_deactivate/index.html
similarity index 100%
rename from modules/@angular/examples/router/ts/can_deactivate/index.html
rename to modules/@angular/examples/router_deprecated/ts/can_deactivate/index.html
diff --git a/modules/@angular/examples/router/ts/on_activate/on_activate_example.ts b/modules/@angular/examples/router_deprecated/ts/on_activate/on_activate_example.ts
similarity index 100%
rename from modules/@angular/examples/router/ts/on_activate/on_activate_example.ts
rename to modules/@angular/examples/router_deprecated/ts/on_activate/on_activate_example.ts
diff --git a/modules/@angular/examples/router/ts/on_deactivate/index.html b/modules/@angular/examples/router_deprecated/ts/on_deactivate/index.html
similarity index 100%
rename from modules/@angular/examples/router/ts/on_deactivate/index.html
rename to modules/@angular/examples/router_deprecated/ts/on_deactivate/index.html
diff --git a/modules/@angular/examples/router/ts/on_deactivate/on_deactivate_example.ts b/modules/@angular/examples/router_deprecated/ts/on_deactivate/on_deactivate_example.ts
similarity index 100%
rename from modules/@angular/examples/router/ts/on_deactivate/on_deactivate_example.ts
rename to modules/@angular/examples/router_deprecated/ts/on_deactivate/on_deactivate_example.ts
diff --git a/modules/@angular/examples/router/ts/on_deactivate/on_deactivate_spec.ts b/modules/@angular/examples/router_deprecated/ts/on_deactivate/on_deactivate_spec.ts
similarity index 100%
rename from modules/@angular/examples/router/ts/on_deactivate/on_deactivate_spec.ts
rename to modules/@angular/examples/router_deprecated/ts/on_deactivate/on_deactivate_spec.ts
diff --git a/modules/@angular/examples/router/ts/reuse/index.html b/modules/@angular/examples/router_deprecated/ts/reuse/index.html
similarity index 100%
rename from modules/@angular/examples/router/ts/reuse/index.html
rename to modules/@angular/examples/router_deprecated/ts/reuse/index.html
diff --git a/modules/@angular/examples/router/ts/reuse/reuse_example.ts b/modules/@angular/examples/router_deprecated/ts/reuse/reuse_example.ts
similarity index 100%
rename from modules/@angular/examples/router/ts/reuse/reuse_example.ts
rename to modules/@angular/examples/router_deprecated/ts/reuse/reuse_example.ts
diff --git a/modules/@angular/examples/router/ts/reuse/reuse_spec.ts b/modules/@angular/examples/router_deprecated/ts/reuse/reuse_spec.ts
similarity index 100%
rename from modules/@angular/examples/router/ts/reuse/reuse_spec.ts
rename to modules/@angular/examples/router_deprecated/ts/reuse/reuse_spec.ts
diff --git a/modules/@angular/router/core_private.dart b/modules/@angular/router-deprecated/core_private.dart
similarity index 100%
rename from modules/@angular/router/core_private.dart
rename to modules/@angular/router-deprecated/core_private.dart
diff --git a/modules/@angular/router/core_private.ts b/modules/@angular/router-deprecated/core_private.ts
similarity index 100%
rename from modules/@angular/router/core_private.ts
rename to modules/@angular/router-deprecated/core_private.ts
diff --git a/modules/@angular/router-deprecated/index.ts b/modules/@angular/router-deprecated/index.ts
new file mode 100644
index 0000000000..164ab508b5
--- /dev/null
+++ b/modules/@angular/router-deprecated/index.ts
@@ -0,0 +1 @@
+export * from './router';
diff --git a/modules/@angular/router/package.json b/modules/@angular/router-deprecated/package.json
similarity index 100%
rename from modules/@angular/router/package.json
rename to modules/@angular/router-deprecated/package.json
diff --git a/modules/@angular/router/rollup.config.js b/modules/@angular/router-deprecated/rollup.config.js
similarity index 100%
rename from modules/@angular/router/rollup.config.js
rename to modules/@angular/router-deprecated/rollup.config.js
diff --git a/modules/@angular/router/router.ts b/modules/@angular/router-deprecated/router.ts
similarity index 100%
rename from modules/@angular/router/router.ts
rename to modules/@angular/router-deprecated/router.ts
diff --git a/modules/@angular/router-deprecated/src/directives/router_link.ts b/modules/@angular/router-deprecated/src/directives/router_link.ts
new file mode 100644
index 0000000000..a86c7fa3a8
--- /dev/null
+++ b/modules/@angular/router-deprecated/src/directives/router_link.ts
@@ -0,0 +1,83 @@
+import {Directive} from '@angular/core';
+import {Location} from '@angular/common';
+import {isString} from '../../src/facade/lang';
+import {Router} from '../router';
+import {Instruction} from '../instruction';
+
+/**
+ * The RouterLink directive lets you link to specific parts of your app.
+ *
+ * Consider the following route configuration:
+
+ * ```
+ * @RouteConfig([
+ * { path: '/user', component: UserCmp, as: 'User' }
+ * ]);
+ * class MyComp {}
+ * ```
+ *
+ * When linking to this `User` route, you can write:
+ *
+ * ```
+ * link to user component
+ * ```
+ *
+ * RouterLink expects the value to be an array of route names, followed by the params
+ * for that level of routing. For instance `['/Team', {teamId: 1}, 'User', {userId: 2}]`
+ * means that we want to generate a link for the `Team` route with params `{teamId: 1}`,
+ * and with a child route `User` with params `{userId: 2}`.
+ *
+ * The first route name should be prepended with `/`, `./`, or `../`.
+ * If the route begins with `/`, the router will look up the route from the root of the app.
+ * If the route begins with `./`, the router will instead look in the current component's
+ * children for the route. And if the route begins with `../`, the router will look at the
+ * current component's parent.
+ */
+@Directive({
+ selector: '[routerLink]',
+ inputs: ['routeParams: routerLink', 'target: target'],
+ host: {
+ '(click)': 'onClick()',
+ '[attr.href]': 'visibleHref',
+ '[class.router-link-active]': 'isRouteActive'
+ }
+})
+export class RouterLink {
+ private _routeParams: any[];
+
+ // the url displayed on the anchor element.
+ visibleHref: string;
+ target: string;
+
+ // the instruction passed to the router to navigate
+ private _navigationInstruction: Instruction;
+
+ constructor(private _router: Router, private _location: Location) {
+ // we need to update the link whenever a route changes to account for aux routes
+ this._router.subscribe((_) => this._updateLink());
+ }
+
+ // because auxiliary links take existing primary and auxiliary routes into account,
+ // we need to update the link whenever params or other routes change.
+ private _updateLink(): void {
+ this._navigationInstruction = this._router.generate(this._routeParams);
+ var navigationHref = this._navigationInstruction.toLinkUrl();
+ this.visibleHref = this._location.prepareExternalUrl(navigationHref);
+ }
+
+ get isRouteActive(): boolean { return this._router.isRouteActive(this._navigationInstruction); }
+
+ set routeParams(changes: any[]) {
+ this._routeParams = changes;
+ this._updateLink();
+ }
+
+ onClick(): boolean {
+ // If no target, or if target is _self, prevent default browser behavior
+ if (!isString(this.target) || this.target == '_self') {
+ this._router.navigateByInstruction(this._navigationInstruction);
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/modules/@angular/router-deprecated/src/directives/router_outlet.ts b/modules/@angular/router-deprecated/src/directives/router_outlet.ts
new file mode 100644
index 0000000000..f7279758fe
--- /dev/null
+++ b/modules/@angular/router-deprecated/src/directives/router_outlet.ts
@@ -0,0 +1,176 @@
+import {PromiseWrapper, EventEmitter} from '../../src/facade/async';
+import {StringMapWrapper} from '../../src/facade/collection';
+import {isBlank, isPresent} from '../../src/facade/lang';
+import {
+ Directive,
+ Attribute,
+ DynamicComponentLoader,
+ ComponentRef,
+ ViewContainerRef,
+ provide,
+ ReflectiveInjector,
+ OnDestroy,
+ Output
+} from '@angular/core';
+import * as routerMod from '../router';
+import {ComponentInstruction, RouteParams, RouteData} from '../instruction';
+import * as hookMod from '../lifecycle/lifecycle_annotations';
+import {hasLifecycleHook} from '../lifecycle/route_lifecycle_reflector';
+import {OnActivate, CanReuse, OnReuse, OnDeactivate, CanDeactivate} from '../interfaces';
+
+let _resolveToTrue = PromiseWrapper.resolve(true);
+
+/**
+ * A router outlet is a placeholder that Angular dynamically fills based on the application's route.
+ *
+ * ## Use
+ *
+ * ```
+ *
+ * ```
+ */
+@Directive({selector: 'router-outlet'})
+export class RouterOutlet implements OnDestroy {
+ name: string = null;
+ private _componentRef: Promise> = null;
+ private _currentInstruction: ComponentInstruction = null;
+
+ @Output('activate') public activateEvents = new EventEmitter();
+
+ constructor(private _viewContainerRef: ViewContainerRef, private _loader: DynamicComponentLoader,
+ private _parentRouter: routerMod.Router, @Attribute('name') nameAttr: string) {
+ if (isPresent(nameAttr)) {
+ this.name = nameAttr;
+ this._parentRouter.registerAuxOutlet(this);
+ } else {
+ this._parentRouter.registerPrimaryOutlet(this);
+ }
+ }
+
+ /**
+ * Called by the Router to instantiate a new component during the commit phase of a navigation.
+ * This method in turn is responsible for calling the `routerOnActivate` hook of its child.
+ */
+ activate(nextInstruction: ComponentInstruction): Promise {
+ var previousInstruction = this._currentInstruction;
+ this._currentInstruction = nextInstruction;
+ var componentType = nextInstruction.componentType;
+ var childRouter = this._parentRouter.childRouter(componentType);
+
+ var providers = ReflectiveInjector.resolve([
+ provide(RouteData, {useValue: nextInstruction.routeData}),
+ provide(RouteParams, {useValue: new RouteParams(nextInstruction.params)}),
+ provide(routerMod.Router, {useValue: childRouter})
+ ]);
+ this._componentRef =
+ this._loader.loadNextToLocation(componentType, this._viewContainerRef, providers);
+ return this._componentRef.then((componentRef) => {
+ this.activateEvents.emit(componentRef.instance);
+ if (hasLifecycleHook(hookMod.routerOnActivate, componentType)) {
+ return this._componentRef.then(
+ (ref: ComponentRef) =>
+ (ref.instance).routerOnActivate(nextInstruction, previousInstruction));
+ } else {
+ return componentRef;
+ }
+ });
+ }
+
+ /**
+ * Called by the {@link Router} during the commit phase of a navigation when an outlet
+ * reuses a component between different routes.
+ * This method in turn is responsible for calling the `routerOnReuse` hook of its child.
+ */
+ reuse(nextInstruction: ComponentInstruction): Promise {
+ var previousInstruction = this._currentInstruction;
+ this._currentInstruction = nextInstruction;
+
+ // it's possible the component is removed before it can be reactivated (if nested withing
+ // another dynamically loaded component, for instance). In that case, we simply activate
+ // a new one.
+ if (isBlank(this._componentRef)) {
+ return this.activate(nextInstruction);
+ } else {
+ return PromiseWrapper.resolve(
+ hasLifecycleHook(hookMod.routerOnReuse, this._currentInstruction.componentType) ?
+ this._componentRef.then(
+ (ref: ComponentRef) =>
+ (ref.instance).routerOnReuse(nextInstruction, previousInstruction)) :
+ true);
+ }
+ }
+
+ /**
+ * Called by the {@link Router} when an outlet disposes of a component's contents.
+ * This method in turn is responsible for calling the `routerOnDeactivate` hook of its child.
+ */
+ deactivate(nextInstruction: ComponentInstruction): Promise {
+ var next = _resolveToTrue;
+ if (isPresent(this._componentRef) && isPresent(this._currentInstruction) &&
+ hasLifecycleHook(hookMod.routerOnDeactivate, this._currentInstruction.componentType)) {
+ next = this._componentRef.then(
+ (ref: ComponentRef) =>
+ (ref.instance)
+ .routerOnDeactivate(nextInstruction, this._currentInstruction));
+ }
+ return next.then((_) => {
+ if (isPresent(this._componentRef)) {
+ var onDispose = this._componentRef.then((ref: ComponentRef) => ref.destroy());
+ this._componentRef = null;
+ return onDispose;
+ }
+ });
+ }
+
+ /**
+ * Called by the {@link Router} during recognition phase of a navigation.
+ *
+ * If this resolves to `false`, the given navigation is cancelled.
+ *
+ * This method delegates to the child component's `routerCanDeactivate` hook if it exists,
+ * and otherwise resolves to true.
+ */
+ routerCanDeactivate(nextInstruction: ComponentInstruction): Promise {
+ if (isBlank(this._currentInstruction)) {
+ return _resolveToTrue;
+ }
+ if (hasLifecycleHook(hookMod.routerCanDeactivate, this._currentInstruction.componentType)) {
+ return this._componentRef.then(
+ (ref: ComponentRef) =>
+ (ref.instance)
+ .routerCanDeactivate(nextInstruction, this._currentInstruction));
+ } else {
+ return _resolveToTrue;
+ }
+ }
+
+ /**
+ * Called by the {@link Router} during recognition phase of a navigation.
+ *
+ * If the new child component has a different Type than the existing child component,
+ * this will resolve to `false`. You can't reuse an old component when the new component
+ * is of a different Type.
+ *
+ * Otherwise, this method delegates to the child component's `routerCanReuse` hook if it exists,
+ * or resolves to true if the hook is not present.
+ */
+ routerCanReuse(nextInstruction: ComponentInstruction): Promise {
+ var result;
+
+ if (isBlank(this._currentInstruction) ||
+ this._currentInstruction.componentType != nextInstruction.componentType) {
+ result = false;
+ } else if (hasLifecycleHook(hookMod.routerCanReuse, this._currentInstruction.componentType)) {
+ result = this._componentRef.then(
+ (ref: ComponentRef) =>
+ (ref.instance).routerCanReuse(nextInstruction, this._currentInstruction));
+ } else {
+ result = nextInstruction == this._currentInstruction ||
+ (isPresent(nextInstruction.params) && isPresent(this._currentInstruction.params) &&
+ StringMapWrapper.equals(nextInstruction.params, this._currentInstruction.params));
+ }
+ return >PromiseWrapper.resolve(result);
+ }
+
+ ngOnDestroy(): void { this._parentRouter.unregisterPrimaryOutlet(this); }
+}
diff --git a/modules/@angular/router/src/facade b/modules/@angular/router-deprecated/src/facade
similarity index 100%
rename from modules/@angular/router/src/facade
rename to modules/@angular/router-deprecated/src/facade
diff --git a/modules/@angular/router/src/instruction.ts b/modules/@angular/router-deprecated/src/instruction.ts
similarity index 100%
rename from modules/@angular/router/src/instruction.ts
rename to modules/@angular/router-deprecated/src/instruction.ts
diff --git a/modules/@angular/router-deprecated/src/interfaces.ts b/modules/@angular/router-deprecated/src/interfaces.ts
new file mode 100644
index 0000000000..1298448a0f
--- /dev/null
+++ b/modules/@angular/router-deprecated/src/interfaces.ts
@@ -0,0 +1,124 @@
+import {ComponentInstruction} from './instruction';
+import {global} from '../src/facade/lang';
+
+// This is here only so that after TS transpilation the file is not empty.
+// TODO(rado): find a better way to fix this, or remove if likely culprit
+// https://github.com/systemjs/systemjs/issues/487 gets closed.
+var __ignore_me = global;
+var __make_dart_analyzer_happy: Promise = null;
+
+/**
+ * Defines route lifecycle method `routerOnActivate`, which is called by the router at the end of a
+ * successful route navigation.
+ *
+ * For a single component's navigation, only one of either {@link OnActivate} or {@link OnReuse}
+ * will be called depending on the result of {@link CanReuse}.
+ *
+ * The `routerOnActivate` hook is called with two {@link ComponentInstruction}s as parameters, the
+ * first
+ * representing the current route being navigated to, and the second parameter representing the
+ * previous route or `null`.
+ *
+ * If `routerOnActivate` returns a promise, the route change will wait until the promise settles to
+ * instantiate and activate child components.
+ *
+ * ### Example
+ * {@example router/ts/on_activate/on_activate_example.ts region='routerOnActivate'}
+ */
+export interface OnActivate {
+ routerOnActivate(nextInstruction: ComponentInstruction,
+ prevInstruction: ComponentInstruction): any |
+ Promise;
+}
+
+/**
+ * Defines route lifecycle method `routerOnReuse`, which is called by the router at the end of a
+ * successful route navigation when {@link CanReuse} is implemented and returns or resolves to true.
+ *
+ * For a single component's navigation, only one of either {@link OnActivate} or {@link OnReuse}
+ * will be called, depending on the result of {@link CanReuse}.
+ *
+ * The `routerOnReuse` hook is called with two {@link ComponentInstruction}s as parameters, the
+ * first
+ * representing the current route being navigated to, and the second parameter representing the
+ * previous route or `null`.
+ *
+ * ### Example
+ * {@example router/ts/reuse/reuse_example.ts region='reuseCmp'}
+ */
+export interface OnReuse {
+ routerOnReuse(nextInstruction: ComponentInstruction, prevInstruction: ComponentInstruction): any |
+ Promise;
+}
+
+/**
+ * Defines route lifecycle method `routerOnDeactivate`, which is called by the router before
+ * destroying
+ * a component as part of a route change.
+ *
+ * The `routerOnDeactivate` hook is called with two {@link ComponentInstruction}s as parameters, the
+ * first
+ * representing the current route being navigated to, and the second parameter representing the
+ * previous route.
+ *
+ * If `routerOnDeactivate` returns a promise, the route change will wait until the promise settles.
+ *
+ * ### Example
+ * {@example router/ts/on_deactivate/on_deactivate_example.ts region='routerOnDeactivate'}
+ */
+export interface OnDeactivate {
+ routerOnDeactivate(nextInstruction: ComponentInstruction,
+ prevInstruction: ComponentInstruction): any |
+ Promise;
+}
+
+/**
+ * Defines route lifecycle method `routerCanReuse`, which is called by the router to determine
+ * whether a
+ * component should be reused across routes, or whether to destroy and instantiate a new component.
+ *
+ * The `routerCanReuse` hook is called with two {@link ComponentInstruction}s as parameters, the
+ * first
+ * representing the current route being navigated to, and the second parameter representing the
+ * previous route.
+ *
+ * If `routerCanReuse` returns or resolves to `true`, the component instance will be reused and the
+ * {@link OnDeactivate} hook will be run. If `routerCanReuse` returns or resolves to `false`, a new
+ * component will be instantiated, and the existing component will be deactivated and removed as
+ * part of the navigation.
+ *
+ * If `routerCanReuse` throws or rejects, the navigation will be cancelled.
+ *
+ * ### Example
+ * {@example router/ts/reuse/reuse_example.ts region='reuseCmp'}
+ */
+export interface CanReuse {
+ routerCanReuse(nextInstruction: ComponentInstruction,
+ prevInstruction: ComponentInstruction): boolean |
+ Promise;
+}
+
+/**
+ * Defines route lifecycle method `routerCanDeactivate`, which is called by the router to determine
+ * if a component can be removed as part of a navigation.
+ *
+ * The `routerCanDeactivate` hook is called with two {@link ComponentInstruction}s as parameters,
+ * the
+ * first representing the current route being navigated to, and the second parameter
+ * representing the previous route.
+ *
+ * If `routerCanDeactivate` returns or resolves to `false`, the navigation is cancelled. If it
+ * returns or
+ * resolves to `true`, then the navigation continues, and the component will be deactivated
+ * (the {@link OnDeactivate} hook will be run) and removed.
+ *
+ * If `routerCanDeactivate` throws or rejects, the navigation is also cancelled.
+ *
+ * ### Example
+ * {@example router/ts/can_deactivate/can_deactivate_example.ts region='routerCanDeactivate'}
+ */
+export interface CanDeactivate {
+ routerCanDeactivate(nextInstruction: ComponentInstruction,
+ prevInstruction: ComponentInstruction): boolean |
+ Promise;
+}
diff --git a/modules/@angular/router/src/lifecycle/lifecycle_annotations.dart b/modules/@angular/router-deprecated/src/lifecycle/lifecycle_annotations.dart
similarity index 100%
rename from modules/@angular/router/src/lifecycle/lifecycle_annotations.dart
rename to modules/@angular/router-deprecated/src/lifecycle/lifecycle_annotations.dart
diff --git a/modules/@angular/router/src/lifecycle/lifecycle_annotations.ts b/modules/@angular/router-deprecated/src/lifecycle/lifecycle_annotations.ts
similarity index 100%
rename from modules/@angular/router/src/lifecycle/lifecycle_annotations.ts
rename to modules/@angular/router-deprecated/src/lifecycle/lifecycle_annotations.ts
diff --git a/modules/@angular/router/src/lifecycle/lifecycle_annotations_impl.ts b/modules/@angular/router-deprecated/src/lifecycle/lifecycle_annotations_impl.ts
similarity index 100%
rename from modules/@angular/router/src/lifecycle/lifecycle_annotations_impl.ts
rename to modules/@angular/router-deprecated/src/lifecycle/lifecycle_annotations_impl.ts
diff --git a/modules/@angular/router/src/lifecycle/route_lifecycle_reflector.dart b/modules/@angular/router-deprecated/src/lifecycle/route_lifecycle_reflector.dart
similarity index 100%
rename from modules/@angular/router/src/lifecycle/route_lifecycle_reflector.dart
rename to modules/@angular/router-deprecated/src/lifecycle/route_lifecycle_reflector.dart
diff --git a/modules/@angular/router/src/lifecycle/route_lifecycle_reflector.ts b/modules/@angular/router-deprecated/src/lifecycle/route_lifecycle_reflector.ts
similarity index 100%
rename from modules/@angular/router/src/lifecycle/route_lifecycle_reflector.ts
rename to modules/@angular/router-deprecated/src/lifecycle/route_lifecycle_reflector.ts
diff --git a/modules/@angular/router/src/package.json b/modules/@angular/router-deprecated/src/package.json
similarity index 100%
rename from modules/@angular/router/src/package.json
rename to modules/@angular/router-deprecated/src/package.json
diff --git a/modules/@angular/router/src/route_config/route_config_decorator.dart b/modules/@angular/router-deprecated/src/route_config/route_config_decorator.dart
similarity index 100%
rename from modules/@angular/router/src/route_config/route_config_decorator.dart
rename to modules/@angular/router-deprecated/src/route_config/route_config_decorator.dart
diff --git a/modules/@angular/router/src/route_config/route_config_decorator.ts b/modules/@angular/router-deprecated/src/route_config/route_config_decorator.ts
similarity index 100%
rename from modules/@angular/router/src/route_config/route_config_decorator.ts
rename to modules/@angular/router-deprecated/src/route_config/route_config_decorator.ts
diff --git a/modules/@angular/router/src/route_config/route_config_impl.ts b/modules/@angular/router-deprecated/src/route_config/route_config_impl.ts
similarity index 100%
rename from modules/@angular/router/src/route_config/route_config_impl.ts
rename to modules/@angular/router-deprecated/src/route_config/route_config_impl.ts
diff --git a/modules/@angular/router/src/route_config/route_config_normalizer.dart b/modules/@angular/router-deprecated/src/route_config/route_config_normalizer.dart
similarity index 100%
rename from modules/@angular/router/src/route_config/route_config_normalizer.dart
rename to modules/@angular/router-deprecated/src/route_config/route_config_normalizer.dart
diff --git a/modules/@angular/router/src/route_config/route_config_normalizer.ts b/modules/@angular/router-deprecated/src/route_config/route_config_normalizer.ts
similarity index 100%
rename from modules/@angular/router/src/route_config/route_config_normalizer.ts
rename to modules/@angular/router-deprecated/src/route_config/route_config_normalizer.ts
diff --git a/modules/@angular/router/src/route_definition.dart b/modules/@angular/router-deprecated/src/route_definition.dart
similarity index 100%
rename from modules/@angular/router/src/route_definition.dart
rename to modules/@angular/router-deprecated/src/route_definition.dart
diff --git a/modules/@angular/router/src/route_definition.ts b/modules/@angular/router-deprecated/src/route_definition.ts
similarity index 100%
rename from modules/@angular/router/src/route_definition.ts
rename to modules/@angular/router-deprecated/src/route_definition.ts
diff --git a/modules/@angular/router/src/route_registry.ts b/modules/@angular/router-deprecated/src/route_registry.ts
similarity index 100%
rename from modules/@angular/router/src/route_registry.ts
rename to modules/@angular/router-deprecated/src/route_registry.ts
diff --git a/modules/@angular/router-deprecated/src/router.ts b/modules/@angular/router-deprecated/src/router.ts
new file mode 100644
index 0000000000..7587686a21
--- /dev/null
+++ b/modules/@angular/router-deprecated/src/router.ts
@@ -0,0 +1,578 @@
+import {PromiseWrapper, EventEmitter, ObservableWrapper} from '../src/facade/async';
+import {Map, StringMapWrapper} from '../src/facade/collection';
+import {isBlank, isPresent, Type} from '../src/facade/lang';
+import {BaseException} from '../src/facade/exceptions';
+import {Location} from '@angular/common';
+import {RouteRegistry, ROUTER_PRIMARY_COMPONENT} from './route_registry';
+import {ComponentInstruction, Instruction} from './instruction';
+import {RouterOutlet} from './directives/router_outlet';
+import {getCanActivateHook} from './lifecycle/route_lifecycle_reflector';
+import {RouteDefinition} from './route_config/route_config_impl';
+import {Injectable, Inject} from '@angular/core';
+
+let _resolveToTrue = PromiseWrapper.resolve(true);
+let _resolveToFalse = PromiseWrapper.resolve(false);
+
+/**
+ * The `Router` is responsible for mapping URLs to components.
+ *
+ * You can see the state of the router by inspecting the read-only field `router.navigating`.
+ * This may be useful for showing a spinner, for instance.
+ *
+ * ## Concepts
+ *
+ * Routers and component instances have a 1:1 correspondence.
+ *
+ * The router holds reference to a number of {@link RouterOutlet}.
+ * An outlet is a placeholder that the router dynamically fills in depending on the current URL.
+ *
+ * When the router navigates from a URL, it must first recognize it and serialize it into an
+ * `Instruction`.
+ * The router uses the `RouteRegistry` to get an `Instruction`.
+ */
+@Injectable()
+export class Router {
+ navigating: boolean = false;
+ lastNavigationAttempt: string;
+ /**
+ * The current `Instruction` for the router
+ */
+ public currentInstruction: Instruction = null;
+
+ private _currentNavigation: Promise = _resolveToTrue;
+ private _outlet: RouterOutlet = null;
+
+ private _auxRouters = new Map();
+ private _childRouter: Router;
+
+ private _subject: EventEmitter = new EventEmitter();
+
+
+ constructor(public registry: RouteRegistry, public parent: Router, public hostComponent: any,
+ public root?: Router) {}
+
+ /**
+ * Constructs a child router. You probably don't need to use this unless you're writing a reusable
+ * component.
+ */
+ childRouter(hostComponent: any): Router {
+ return this._childRouter = new ChildRouter(this, hostComponent);
+ }
+
+
+ /**
+ * Constructs a child router. You probably don't need to use this unless you're writing a reusable
+ * component.
+ */
+ auxRouter(hostComponent: any): Router { return new ChildRouter(this, hostComponent); }
+
+ /**
+ * Register an outlet to be notified of primary route changes.
+ *
+ * You probably don't need to use this unless you're writing a reusable component.
+ */
+ registerPrimaryOutlet(outlet: RouterOutlet): Promise {
+ if (isPresent(outlet.name)) {
+ throw new BaseException(`registerPrimaryOutlet expects to be called with an unnamed outlet.`);
+ }
+
+ if (isPresent(this._outlet)) {
+ throw new BaseException(`Primary outlet is already registered.`);
+ }
+
+ this._outlet = outlet;
+ if (isPresent(this.currentInstruction)) {
+ return this.commit(this.currentInstruction, false);
+ }
+ return _resolveToTrue;
+ }
+
+ /**
+ * Unregister an outlet (because it was destroyed, etc).
+ *
+ * You probably don't need to use this unless you're writing a custom outlet implementation.
+ */
+ unregisterPrimaryOutlet(outlet: RouterOutlet): void {
+ if (isPresent(outlet.name)) {
+ throw new BaseException(`registerPrimaryOutlet expects to be called with an unnamed outlet.`);
+ }
+ this._outlet = null;
+ }
+
+
+ /**
+ * Register an outlet to notified of auxiliary route changes.
+ *
+ * You probably don't need to use this unless you're writing a reusable component.
+ */
+ registerAuxOutlet(outlet: RouterOutlet): Promise {
+ var outletName = outlet.name;
+ if (isBlank(outletName)) {
+ throw new BaseException(`registerAuxOutlet expects to be called with an outlet with a name.`);
+ }
+
+ var router = this.auxRouter(this.hostComponent);
+
+ this._auxRouters.set(outletName, router);
+ router._outlet = outlet;
+
+ var auxInstruction;
+ if (isPresent(this.currentInstruction) &&
+ isPresent(auxInstruction = this.currentInstruction.auxInstruction[outletName])) {
+ return router.commit(auxInstruction);
+ }
+ return _resolveToTrue;
+ }
+
+
+ /**
+ * Given an instruction, returns `true` if the instruction is currently active,
+ * otherwise `false`.
+ */
+ isRouteActive(instruction: Instruction): boolean {
+ var router: Router = this;
+
+ if (isBlank(this.currentInstruction)) {
+ return false;
+ }
+
+ // `instruction` corresponds to the root router
+ while (isPresent(router.parent) && isPresent(instruction.child)) {
+ router = router.parent;
+ instruction = instruction.child;
+ }
+
+ if (isBlank(instruction.component) || isBlank(this.currentInstruction.component) ||
+ this.currentInstruction.component.routeName != instruction.component.routeName) {
+ return false;
+ }
+
+ let paramEquals = true;
+
+ if (isPresent(this.currentInstruction.component.params)) {
+ StringMapWrapper.forEach(instruction.component.params, (value, key) => {
+ if (this.currentInstruction.component.params[key] !== value) {
+ paramEquals = false;
+ }
+ });
+ }
+
+ return paramEquals;
+ }
+
+
+ /**
+ * Dynamically update the routing configuration and trigger a navigation.
+ *
+ * ### Usage
+ *
+ * ```
+ * router.config([
+ * { 'path': '/', 'component': IndexComp },
+ * { 'path': '/user/:id', 'component': UserComp },
+ * ]);
+ * ```
+ */
+ config(definitions: RouteDefinition[]): Promise {
+ definitions.forEach(
+ (routeDefinition) => { this.registry.config(this.hostComponent, routeDefinition); });
+ return this.renavigate();
+ }
+
+
+ /**
+ * Navigate based on the provided Route Link DSL. It's preferred to navigate with this method
+ * over `navigateByUrl`.
+ *
+ * ### Usage
+ *
+ * This method takes an array representing the Route Link DSL:
+ * ```
+ * ['./MyCmp', {param: 3}]
+ * ```
+ * See the {@link RouterLink} directive for more.
+ */
+ navigate(linkParams: any[]): Promise {
+ var instruction = this.generate(linkParams);
+ return this.navigateByInstruction(instruction, false);
+ }
+
+
+ /**
+ * Navigate to a URL. Returns a promise that resolves when navigation is complete.
+ * It's preferred to navigate with `navigate` instead of this method, since URLs are more brittle.
+ *
+ * If the given URL begins with a `/`, router will navigate absolutely.
+ * If the given URL does not begin with `/`, the router will navigate relative to this component.
+ */
+ navigateByUrl(url: string, _skipLocationChange: boolean = false): Promise {
+ return this._currentNavigation = this._currentNavigation.then((_) => {
+ this.lastNavigationAttempt = url;
+ this._startNavigating();
+ return this._afterPromiseFinishNavigating(this.recognize(url).then((instruction) => {
+ if (isBlank(instruction)) {
+ return false;
+ }
+ return this._navigate(instruction, _skipLocationChange);
+ }));
+ });
+ }
+
+
+ /**
+ * Navigate via the provided instruction. Returns a promise that resolves when navigation is
+ * complete.
+ */
+ navigateByInstruction(instruction: Instruction,
+ _skipLocationChange: boolean = false): Promise {
+ if (isBlank(instruction)) {
+ return _resolveToFalse;
+ }
+ return this._currentNavigation = this._currentNavigation.then((_) => {
+ this._startNavigating();
+ return this._afterPromiseFinishNavigating(this._navigate(instruction, _skipLocationChange));
+ });
+ }
+
+ /** @internal */
+ _settleInstruction(instruction: Instruction): Promise {
+ return instruction.resolveComponent().then((_) => {
+ var unsettledInstructions: Array> = [];
+
+ if (isPresent(instruction.component)) {
+ instruction.component.reuse = false;
+ }
+
+ if (isPresent(instruction.child)) {
+ unsettledInstructions.push(this._settleInstruction(instruction.child));
+ }
+
+ StringMapWrapper.forEach(instruction.auxInstruction, (instruction: Instruction, _) => {
+ unsettledInstructions.push(this._settleInstruction(instruction));
+ });
+ return PromiseWrapper.all(unsettledInstructions);
+ });
+ }
+
+ /** @internal */
+ _navigate(instruction: Instruction, _skipLocationChange: boolean): Promise {
+ return this._settleInstruction(instruction)
+ .then((_) => this._routerCanReuse(instruction))
+ .then((_) => this._canActivate(instruction))
+ .then((result: boolean) => {
+ if (!result) {
+ return false;
+ }
+ return this._routerCanDeactivate(instruction)
+ .then((result: boolean) => {
+ if (result) {
+ return this.commit(instruction, _skipLocationChange)
+ .then((_) => {
+ this._emitNavigationFinish(instruction.toRootUrl());
+ return true;
+ });
+ }
+ });
+ });
+ }
+
+ private _emitNavigationFinish(url): void { ObservableWrapper.callEmit(this._subject, url); }
+ /** @internal */
+ _emitNavigationFail(url): void { ObservableWrapper.callError(this._subject, url); }
+
+ private _afterPromiseFinishNavigating(promise: Promise): Promise {
+ return PromiseWrapper.catchError(promise.then((_) => this._finishNavigating()), (err) => {
+ this._finishNavigating();
+ throw err;
+ });
+ }
+
+ /*
+ * Recursively set reuse flags
+ */
+ /** @internal */
+ _routerCanReuse(instruction: Instruction): Promise {
+ if (isBlank(this._outlet)) {
+ return _resolveToFalse;
+ }
+ if (isBlank(instruction.component)) {
+ return _resolveToTrue;
+ }
+ return this._outlet.routerCanReuse(instruction.component)
+ .then((result) => {
+ instruction.component.reuse = result;
+ if (result && isPresent(this._childRouter) && isPresent(instruction.child)) {
+ return this._childRouter._routerCanReuse(instruction.child);
+ }
+ });
+ }
+
+ private _canActivate(nextInstruction: Instruction): Promise {
+ return canActivateOne(nextInstruction, this.currentInstruction);
+ }
+
+ private _routerCanDeactivate(instruction: Instruction): Promise {
+ if (isBlank(this._outlet)) {
+ return _resolveToTrue;
+ }
+ var next: Promise;
+ var childInstruction: Instruction = null;
+ var reuse: boolean = false;
+ var componentInstruction: ComponentInstruction = null;
+ if (isPresent(instruction)) {
+ childInstruction = instruction.child;
+ componentInstruction = instruction.component;
+ reuse = isBlank(instruction.component) || instruction.component.reuse;
+ }
+ if (reuse) {
+ next = _resolveToTrue;
+ } else {
+ next = this._outlet.routerCanDeactivate(componentInstruction);
+ }
+ // TODO: aux route lifecycle hooks
+ return next.then((result): boolean | Promise => {
+ if (result == false) {
+ return false;
+ }
+ if (isPresent(this._childRouter)) {
+ // TODO: ideally, this closure would map to async-await in Dart.
+ // For now, casting to any to suppress an error.
+ return this._childRouter._routerCanDeactivate(childInstruction);
+ }
+ return true;
+ });
+ }
+
+ /**
+ * Updates this router and all descendant routers according to the given instruction
+ */
+ commit(instruction: Instruction, _skipLocationChange: boolean = false): Promise {
+ this.currentInstruction = instruction;
+
+ var next: Promise = _resolveToTrue;
+ if (isPresent(this._outlet) && isPresent(instruction.component)) {
+ var componentInstruction = instruction.component;
+ if (componentInstruction.reuse) {
+ next = this._outlet.reuse(componentInstruction);
+ } else {
+ next =
+ this.deactivate(instruction).then((_) => this._outlet.activate(componentInstruction));
+ }
+ if (isPresent(instruction.child)) {
+ next = next.then((_) => {
+ if (isPresent(this._childRouter)) {
+ return this._childRouter.commit(instruction.child);
+ }
+ });
+ }
+ }
+
+ var promises: Promise[] = [];
+ this._auxRouters.forEach((router, name) => {
+ if (isPresent(instruction.auxInstruction[name])) {
+ promises.push(router.commit(instruction.auxInstruction[name]));
+ }
+ });
+
+ return next.then((_) => PromiseWrapper.all(promises));
+ }
+
+
+ /** @internal */
+ _startNavigating(): void { this.navigating = true; }
+
+ /** @internal */
+ _finishNavigating(): void { this.navigating = false; }
+
+
+ /**
+ * Subscribe to URL updates from the router
+ */
+ subscribe(onNext: (value: any) => void, onError?: (value: any) => void): Object {
+ return ObservableWrapper.subscribe(this._subject, onNext, onError);
+ }
+
+
+ /**
+ * Removes the contents of this router's outlet and all descendant outlets
+ */
+ deactivate(instruction: Instruction): Promise {
+ var childInstruction: Instruction = null;
+ var componentInstruction: ComponentInstruction = null;
+ if (isPresent(instruction)) {
+ childInstruction = instruction.child;
+ componentInstruction = instruction.component;
+ }
+ var next: Promise = _resolveToTrue;
+ if (isPresent(this._childRouter)) {
+ next = this._childRouter.deactivate(childInstruction);
+ }
+ if (isPresent(this._outlet)) {
+ next = next.then((_) => this._outlet.deactivate(componentInstruction));
+ }
+
+ // TODO: handle aux routes
+
+ return next;
+ }
+
+
+ /**
+ * Given a URL, returns an instruction representing the component graph
+ */
+ recognize(url: string): Promise {
+ var ancestorComponents = this._getAncestorInstructions();
+ return this.registry.recognize(url, ancestorComponents);
+ }
+
+ private _getAncestorInstructions(): Instruction[] {
+ var ancestorInstructions: Instruction[] = [this.currentInstruction];
+ var ancestorRouter: Router = this;
+ while (isPresent(ancestorRouter = ancestorRouter.parent)) {
+ ancestorInstructions.unshift(ancestorRouter.currentInstruction);
+ }
+ return ancestorInstructions;
+ }
+
+
+ /**
+ * Navigates to either the last URL successfully navigated to, or the last URL requested if the
+ * router has yet to successfully navigate.
+ */
+ renavigate(): Promise {
+ if (isBlank(this.lastNavigationAttempt)) {
+ return this._currentNavigation;
+ }
+ return this.navigateByUrl(this.lastNavigationAttempt);
+ }
+
+
+ /**
+ * Generate an `Instruction` based on the provided Route Link DSL.
+ */
+ generate(linkParams: any[]): Instruction {
+ var ancestorInstructions = this._getAncestorInstructions();
+ return this.registry.generate(linkParams, ancestorInstructions);
+ }
+}
+
+@Injectable()
+export class RootRouter extends Router {
+ /** @internal */
+ _location: Location;
+ /** @internal */
+ _locationSub: Object;
+
+ constructor(registry: RouteRegistry, location: Location,
+ @Inject(ROUTER_PRIMARY_COMPONENT) primaryComponent: Type) {
+ super(registry, null, primaryComponent);
+ this.root = this;
+ this._location = location;
+ this._locationSub = this._location.subscribe((change) => {
+ // we call recognize ourselves
+ this.recognize(change['url'])
+ .then((instruction) => {
+ if (isPresent(instruction)) {
+ this.navigateByInstruction(instruction, isPresent(change['pop']))
+ .then((_) => {
+ // this is a popstate event; no need to change the URL
+ if (isPresent(change['pop']) && change['type'] != 'hashchange') {
+ return;
+ }
+ var emitPath = instruction.toUrlPath();
+ var emitQuery = instruction.toUrlQuery();
+ if (emitPath.length > 0 && emitPath[0] != '/') {
+ emitPath = '/' + emitPath;
+ }
+
+ // We've opted to use pushstate and popState APIs regardless of whether you
+ // an app uses HashLocationStrategy or PathLocationStrategy.
+ // However, apps that are migrating might have hash links that operate outside
+ // angular to which routing must respond.
+ // Therefore we know that all hashchange events occur outside Angular.
+ // To support these cases where we respond to hashchanges and redirect as a
+ // result, we need to replace the top item on the stack.
+ if (change['type'] == 'hashchange') {
+ if (instruction.toRootUrl() != this._location.path()) {
+ this._location.replaceState(emitPath, emitQuery);
+ }
+ } else {
+ this._location.go(emitPath, emitQuery);
+ }
+ });
+ } else {
+ this._emitNavigationFail(change['url']);
+ }
+ });
+ });
+
+ this.registry.configFromComponent(primaryComponent);
+ this.navigateByUrl(location.path());
+ }
+
+ commit(instruction: Instruction, _skipLocationChange: boolean = false): Promise {
+ var emitPath = instruction.toUrlPath();
+ var emitQuery = instruction.toUrlQuery();
+ if (emitPath.length > 0 && emitPath[0] != '/') {
+ emitPath = '/' + emitPath;
+ }
+ var promise = super.commit(instruction);
+ if (!_skipLocationChange) {
+ promise = promise.then((_) => { this._location.go(emitPath, emitQuery); });
+ }
+ return promise;
+ }
+
+ dispose(): void {
+ if (isPresent(this._locationSub)) {
+ ObservableWrapper.dispose(this._locationSub);
+ this._locationSub = null;
+ }
+ }
+}
+
+class ChildRouter extends Router {
+ constructor(parent: Router, hostComponent) {
+ super(parent.registry, parent, hostComponent, parent.root);
+ this.parent = parent;
+ }
+
+
+ navigateByUrl(url: string, _skipLocationChange: boolean = false): Promise {
+ // Delegate navigation to the root router
+ return this.parent.navigateByUrl(url, _skipLocationChange);
+ }
+
+ navigateByInstruction(instruction: Instruction,
+ _skipLocationChange: boolean = false): Promise {
+ // Delegate navigation to the root router
+ return this.parent.navigateByInstruction(instruction, _skipLocationChange);
+ }
+}
+
+
+function canActivateOne(nextInstruction: Instruction,
+ prevInstruction: Instruction): Promise {
+ var next = _resolveToTrue;
+ if (isBlank(nextInstruction.component)) {
+ return next;
+ }
+ if (isPresent(nextInstruction.child)) {
+ next = canActivateOne(nextInstruction.child,
+ isPresent(prevInstruction) ? prevInstruction.child : null);
+ }
+ return next.then((result: boolean): boolean => {
+ if (result == false) {
+ return false;
+ }
+ if (nextInstruction.component.reuse) {
+ return true;
+ }
+ var hook = getCanActivateHook(nextInstruction.component.componentType);
+ if (isPresent(hook)) {
+ return hook(nextInstruction.component,
+ isPresent(prevInstruction) ? prevInstruction.component : null);
+ }
+ return true;
+ });
+}
diff --git a/modules/@angular/router-deprecated/src/router_providers.ts b/modules/@angular/router-deprecated/src/router_providers.ts
new file mode 100644
index 0000000000..baddb26ed0
--- /dev/null
+++ b/modules/@angular/router-deprecated/src/router_providers.ts
@@ -0,0 +1,41 @@
+import {ROUTER_PROVIDERS_COMMON} from './router_providers_common';
+import {Provider} from '@angular/core';
+import {BrowserPlatformLocation} from '@angular/platform-browser';
+import {PlatformLocation} from '@angular/common';
+
+/**
+ * A list of {@link Provider}s. To use the router, you must add this to your application.
+ *
+ * ### Example ([live demo](http://plnkr.co/edit/iRUP8B5OUbxCWQ3AcIDm))
+ *
+ * ```
+ * import {Component} from '@angular/core';
+ * import {
+ * ROUTER_DIRECTIVES,
+ * ROUTER_PROVIDERS,
+ * RouteConfig
+ * } from '@angular/router';
+ *
+ * @Component({directives: [ROUTER_DIRECTIVES]})
+ * @RouteConfig([
+ * {...},
+ * ])
+ * class AppCmp {
+ * // ...
+ * }
+ *
+ * bootstrap(AppCmp, [ROUTER_PROVIDERS]);
+ * ```
+ */
+export const ROUTER_PROVIDERS: any[] = /*@ts2dart_const*/[
+ ROUTER_PROVIDERS_COMMON,
+ /*@ts2dart_const*/ (
+ /* @ts2dart_Provider */ {provide: PlatformLocation, useClass: BrowserPlatformLocation}),
+];
+
+/**
+ * Use {@link ROUTER_PROVIDERS} instead.
+ *
+ * @deprecated
+ */
+export const ROUTER_BINDINGS = /*@ts2dart_const*/ ROUTER_PROVIDERS;
diff --git a/modules/@angular/router-deprecated/src/router_providers_common.ts b/modules/@angular/router-deprecated/src/router_providers_common.ts
new file mode 100644
index 0000000000..a9042754e1
--- /dev/null
+++ b/modules/@angular/router-deprecated/src/router_providers_common.ts
@@ -0,0 +1,39 @@
+import {ApplicationRef, Provider} from '@angular/core';
+import {LocationStrategy, PathLocationStrategy, Location} from '@angular/common';
+import {Router, RootRouter} from './router';
+import {RouteRegistry, ROUTER_PRIMARY_COMPONENT} from './route_registry';
+import {Type} from '../src/facade/lang';
+import {BaseException} from '../src/facade/exceptions';
+
+/**
+ * The Platform agnostic ROUTER PROVIDERS
+ */
+export const ROUTER_PROVIDERS_COMMON: any[] = /*@ts2dart_const*/[
+ RouteRegistry,
+ /* @ts2dart_Provider */ {provide: LocationStrategy, useClass: PathLocationStrategy},
+ Location,
+ {
+ provide: Router,
+ useFactory: routerFactory,
+ deps: [RouteRegistry, Location, ROUTER_PRIMARY_COMPONENT, ApplicationRef]
+ },
+ {
+ provide: ROUTER_PRIMARY_COMPONENT,
+ useFactory: routerPrimaryComponentFactory,
+ deps: /*@ts2dart_const*/ ([ApplicationRef])
+ }
+];
+
+function routerFactory(registry: RouteRegistry, location: Location, primaryComponent: Type,
+ appRef: ApplicationRef): RootRouter {
+ var rootRouter = new RootRouter(registry, location, primaryComponent);
+ appRef.registerDisposeListener(() => rootRouter.dispose());
+ return rootRouter;
+}
+
+function routerPrimaryComponentFactory(app: ApplicationRef): Type {
+ if (app.componentTypes.length == 0) {
+ throw new BaseException("Bootstrap at least one component before injecting Router.");
+ }
+ return app.componentTypes[0];
+}
diff --git a/modules/@angular/router/src/rules/route_handlers/async_route_handler.ts b/modules/@angular/router-deprecated/src/rules/route_handlers/async_route_handler.ts
similarity index 100%
rename from modules/@angular/router/src/rules/route_handlers/async_route_handler.ts
rename to modules/@angular/router-deprecated/src/rules/route_handlers/async_route_handler.ts
diff --git a/modules/@angular/router/src/rules/route_handlers/route_handler.ts b/modules/@angular/router-deprecated/src/rules/route_handlers/route_handler.ts
similarity index 100%
rename from modules/@angular/router/src/rules/route_handlers/route_handler.ts
rename to modules/@angular/router-deprecated/src/rules/route_handlers/route_handler.ts
diff --git a/modules/@angular/router/src/rules/route_handlers/sync_route_handler.ts b/modules/@angular/router-deprecated/src/rules/route_handlers/sync_route_handler.ts
similarity index 100%
rename from modules/@angular/router/src/rules/route_handlers/sync_route_handler.ts
rename to modules/@angular/router-deprecated/src/rules/route_handlers/sync_route_handler.ts
diff --git a/modules/@angular/router/src/rules/route_paths/param_route_path.ts b/modules/@angular/router-deprecated/src/rules/route_paths/param_route_path.ts
similarity index 100%
rename from modules/@angular/router/src/rules/route_paths/param_route_path.ts
rename to modules/@angular/router-deprecated/src/rules/route_paths/param_route_path.ts
diff --git a/modules/@angular/router/src/rules/route_paths/regex_route_path.ts b/modules/@angular/router-deprecated/src/rules/route_paths/regex_route_path.ts
similarity index 100%
rename from modules/@angular/router/src/rules/route_paths/regex_route_path.ts
rename to modules/@angular/router-deprecated/src/rules/route_paths/regex_route_path.ts
diff --git a/modules/@angular/router/src/rules/route_paths/route_path.ts b/modules/@angular/router-deprecated/src/rules/route_paths/route_path.ts
similarity index 100%
rename from modules/@angular/router/src/rules/route_paths/route_path.ts
rename to modules/@angular/router-deprecated/src/rules/route_paths/route_path.ts
diff --git a/modules/@angular/router/src/rules/rule_set.ts b/modules/@angular/router-deprecated/src/rules/rule_set.ts
similarity index 100%
rename from modules/@angular/router/src/rules/rule_set.ts
rename to modules/@angular/router-deprecated/src/rules/rule_set.ts
diff --git a/modules/@angular/router/src/rules/rules.ts b/modules/@angular/router-deprecated/src/rules/rules.ts
similarity index 100%
rename from modules/@angular/router/src/rules/rules.ts
rename to modules/@angular/router-deprecated/src/rules/rules.ts
diff --git a/modules/@angular/router/src/url_parser.ts b/modules/@angular/router-deprecated/src/url_parser.ts
similarity index 100%
rename from modules/@angular/router/src/url_parser.ts
rename to modules/@angular/router-deprecated/src/url_parser.ts
diff --git a/modules/@angular/router/src/utils.ts b/modules/@angular/router-deprecated/src/utils.ts
similarity index 100%
rename from modules/@angular/router/src/utils.ts
rename to modules/@angular/router-deprecated/src/utils.ts
diff --git a/modules/@angular/router/test/directives/router_link_spec.ts b/modules/@angular/router-deprecated/test/directives/router_link_spec.ts
similarity index 100%
rename from modules/@angular/router/test/directives/router_link_spec.ts
rename to modules/@angular/router-deprecated/test/directives/router_link_spec.ts
diff --git a/modules/@angular/router/test/integration/README.md b/modules/@angular/router-deprecated/test/integration/README.md
similarity index 100%
rename from modules/@angular/router/test/integration/README.md
rename to modules/@angular/router-deprecated/test/integration/README.md
diff --git a/modules/@angular/router/test/integration/async_route_spec.ts b/modules/@angular/router-deprecated/test/integration/async_route_spec.ts
similarity index 100%
rename from modules/@angular/router/test/integration/async_route_spec.ts
rename to modules/@angular/router-deprecated/test/integration/async_route_spec.ts
diff --git a/modules/@angular/router/test/integration/auxiliary_route_spec.ts b/modules/@angular/router-deprecated/test/integration/auxiliary_route_spec.ts
similarity index 100%
rename from modules/@angular/router/test/integration/auxiliary_route_spec.ts
rename to modules/@angular/router-deprecated/test/integration/auxiliary_route_spec.ts
diff --git a/modules/@angular/router/test/integration/bootstrap_spec.ts b/modules/@angular/router-deprecated/test/integration/bootstrap_spec.ts
similarity index 100%
rename from modules/@angular/router/test/integration/bootstrap_spec.ts
rename to modules/@angular/router-deprecated/test/integration/bootstrap_spec.ts
diff --git a/modules/@angular/router/test/integration/impl/async_route_spec_impl.ts b/modules/@angular/router-deprecated/test/integration/impl/async_route_spec_impl.ts
similarity index 100%
rename from modules/@angular/router/test/integration/impl/async_route_spec_impl.ts
rename to modules/@angular/router-deprecated/test/integration/impl/async_route_spec_impl.ts
diff --git a/modules/@angular/router/test/integration/impl/aux_route_spec_impl.ts b/modules/@angular/router-deprecated/test/integration/impl/aux_route_spec_impl.ts
similarity index 100%
rename from modules/@angular/router/test/integration/impl/aux_route_spec_impl.ts
rename to modules/@angular/router-deprecated/test/integration/impl/aux_route_spec_impl.ts
diff --git a/modules/@angular/router/test/integration/impl/fixture_components.ts b/modules/@angular/router-deprecated/test/integration/impl/fixture_components.ts
similarity index 100%
rename from modules/@angular/router/test/integration/impl/fixture_components.ts
rename to modules/@angular/router-deprecated/test/integration/impl/fixture_components.ts
diff --git a/modules/@angular/router/test/integration/impl/sync_route_spec_impl.ts b/modules/@angular/router-deprecated/test/integration/impl/sync_route_spec_impl.ts
similarity index 100%
rename from modules/@angular/router/test/integration/impl/sync_route_spec_impl.ts
rename to modules/@angular/router-deprecated/test/integration/impl/sync_route_spec_impl.ts
diff --git a/modules/@angular/router/test/integration/lifecycle_hook_spec.ts b/modules/@angular/router-deprecated/test/integration/lifecycle_hook_spec.ts
similarity index 100%
rename from modules/@angular/router/test/integration/lifecycle_hook_spec.ts
rename to modules/@angular/router-deprecated/test/integration/lifecycle_hook_spec.ts
diff --git a/modules/@angular/router/test/integration/navigation_spec.ts b/modules/@angular/router-deprecated/test/integration/navigation_spec.ts
similarity index 100%
rename from modules/@angular/router/test/integration/navigation_spec.ts
rename to modules/@angular/router-deprecated/test/integration/navigation_spec.ts
diff --git a/modules/@angular/router/test/integration/redirect_route_spec.ts b/modules/@angular/router-deprecated/test/integration/redirect_route_spec.ts
similarity index 100%
rename from modules/@angular/router/test/integration/redirect_route_spec.ts
rename to modules/@angular/router-deprecated/test/integration/redirect_route_spec.ts
diff --git a/modules/@angular/router/test/integration/router_link_spec.ts b/modules/@angular/router-deprecated/test/integration/router_link_spec.ts
similarity index 100%
rename from modules/@angular/router/test/integration/router_link_spec.ts
rename to modules/@angular/router-deprecated/test/integration/router_link_spec.ts
diff --git a/modules/@angular/router/test/integration/sync_route_spec.ts b/modules/@angular/router-deprecated/test/integration/sync_route_spec.ts
similarity index 100%
rename from modules/@angular/router/test/integration/sync_route_spec.ts
rename to modules/@angular/router-deprecated/test/integration/sync_route_spec.ts
diff --git a/modules/@angular/router/test/integration/util.ts b/modules/@angular/router-deprecated/test/integration/util.ts
similarity index 100%
rename from modules/@angular/router/test/integration/util.ts
rename to modules/@angular/router-deprecated/test/integration/util.ts
diff --git a/modules/@angular/router/test/location/hash_location_strategy_spec.ts b/modules/@angular/router-deprecated/test/location/hash_location_strategy_spec.ts
similarity index 100%
rename from modules/@angular/router/test/location/hash_location_strategy_spec.ts
rename to modules/@angular/router-deprecated/test/location/hash_location_strategy_spec.ts
diff --git a/modules/@angular/router/test/location/location_spec.ts b/modules/@angular/router-deprecated/test/location/location_spec.ts
similarity index 100%
rename from modules/@angular/router/test/location/location_spec.ts
rename to modules/@angular/router-deprecated/test/location/location_spec.ts
diff --git a/modules/@angular/router/test/location/path_location_strategy_spec.ts b/modules/@angular/router-deprecated/test/location/path_location_strategy_spec.ts
similarity index 100%
rename from modules/@angular/router/test/location/path_location_strategy_spec.ts
rename to modules/@angular/router-deprecated/test/location/path_location_strategy_spec.ts
diff --git a/modules/@angular/router/test/route_config/route_config_spec.dart b/modules/@angular/router-deprecated/test/route_config/route_config_spec.dart
similarity index 100%
rename from modules/@angular/router/test/route_config/route_config_spec.dart
rename to modules/@angular/router-deprecated/test/route_config/route_config_spec.dart
diff --git a/modules/@angular/router/test/route_config/route_config_spec.ts b/modules/@angular/router-deprecated/test/route_config/route_config_spec.ts
similarity index 100%
rename from modules/@angular/router/test/route_config/route_config_spec.ts
rename to modules/@angular/router-deprecated/test/route_config/route_config_spec.ts
diff --git a/modules/@angular/router/test/route_registry_spec.ts b/modules/@angular/router-deprecated/test/route_registry_spec.ts
similarity index 100%
rename from modules/@angular/router/test/route_registry_spec.ts
rename to modules/@angular/router-deprecated/test/route_registry_spec.ts
diff --git a/modules/@angular/router/test/router_spec.ts b/modules/@angular/router-deprecated/test/router_spec.ts
similarity index 100%
rename from modules/@angular/router/test/router_spec.ts
rename to modules/@angular/router-deprecated/test/router_spec.ts
diff --git a/modules/@angular/router/test/rules/route_paths/param_route_path_spec.ts b/modules/@angular/router-deprecated/test/rules/route_paths/param_route_path_spec.ts
similarity index 100%
rename from modules/@angular/router/test/rules/route_paths/param_route_path_spec.ts
rename to modules/@angular/router-deprecated/test/rules/route_paths/param_route_path_spec.ts
diff --git a/modules/@angular/router/test/rules/route_paths/regex_route_param_spec.ts b/modules/@angular/router-deprecated/test/rules/route_paths/regex_route_param_spec.ts
similarity index 100%
rename from modules/@angular/router/test/rules/route_paths/regex_route_param_spec.ts
rename to modules/@angular/router-deprecated/test/rules/route_paths/regex_route_param_spec.ts
diff --git a/modules/@angular/router/test/rules/rule_set_spec.ts b/modules/@angular/router-deprecated/test/rules/rule_set_spec.ts
similarity index 100%
rename from modules/@angular/router/test/rules/rule_set_spec.ts
rename to modules/@angular/router-deprecated/test/rules/rule_set_spec.ts
diff --git a/modules/@angular/router/test/spies.dart b/modules/@angular/router-deprecated/test/spies.dart
similarity index 100%
rename from modules/@angular/router/test/spies.dart
rename to modules/@angular/router-deprecated/test/spies.dart
diff --git a/modules/@angular/router/test/spies.ts b/modules/@angular/router-deprecated/test/spies.ts
similarity index 100%
rename from modules/@angular/router/test/spies.ts
rename to modules/@angular/router-deprecated/test/spies.ts
diff --git a/modules/@angular/router/test/url_parser_spec.ts b/modules/@angular/router-deprecated/test/url_parser_spec.ts
similarity index 100%
rename from modules/@angular/router/test/url_parser_spec.ts
rename to modules/@angular/router-deprecated/test/url_parser_spec.ts
diff --git a/modules/@angular/router/testing.ts b/modules/@angular/router-deprecated/testing.ts
similarity index 100%
rename from modules/@angular/router/testing.ts
rename to modules/@angular/router-deprecated/testing.ts
diff --git a/modules/@angular/router/tsconfig-es2015.json b/modules/@angular/router-deprecated/tsconfig-es2015.json
similarity index 100%
rename from modules/@angular/router/tsconfig-es2015.json
rename to modules/@angular/router-deprecated/tsconfig-es2015.json
diff --git a/modules/@angular/router/tsconfig.json b/modules/@angular/router-deprecated/tsconfig.json
similarity index 100%
rename from modules/@angular/router/tsconfig.json
rename to modules/@angular/router-deprecated/tsconfig.json
diff --git a/modules/@angular/router/index.ts b/modules/@angular/router/index.ts
index 164ab508b5..d7ea77a688 100644
--- a/modules/@angular/router/index.ts
+++ b/modules/@angular/router/index.ts
@@ -1 +1,21 @@
-export * from './router';
+/**
+ * @module
+ * @description
+ * Alternative implementation of the router. Experimental.
+ */
+
+export {Router, RouterOutletMap} from './src/alt_router/router';
+export {RouteSegment, UrlSegment, Tree, UrlTree, RouteTree} from './src/alt_router/segments';
+export {Routes} from './src/alt_router/metadata/decorators';
+export {Route} from './src/alt_router/metadata/metadata';
+export {
+ RouterUrlSerializer,
+ DefaultRouterUrlSerializer
+} from './src/alt_router/router_url_serializer';
+export {OnActivate, CanDeactivate} from './src/alt_router/interfaces';
+export {ROUTER_PROVIDERS} from './src/alt_router/router_providers';
+
+import {RouterOutlet} from './src/alt_router/directives/router_outlet';
+import {RouterLink} from './src/alt_router/directives/router_link';
+
+export const ROUTER_DIRECTIVES: any[] = /*@ts2dart_const*/[RouterOutlet, RouterLink];
diff --git a/modules/angular2/src/alt_router/constants.ts b/modules/@angular/router/src/constants.ts
similarity index 100%
rename from modules/angular2/src/alt_router/constants.ts
rename to modules/@angular/router/src/constants.ts
diff --git a/modules/angular2/src/alt_router/core_private.ts b/modules/@angular/router/src/core_private.ts
similarity index 100%
rename from modules/angular2/src/alt_router/core_private.ts
rename to modules/@angular/router/src/core_private.ts
diff --git a/modules/@angular/router/src/directives/router_link.ts b/modules/@angular/router/src/directives/router_link.ts
index a86c7fa3a8..8c662d3e38 100644
--- a/modules/@angular/router/src/directives/router_link.ts
+++ b/modules/@angular/router/src/directives/router_link.ts
@@ -1,83 +1,62 @@
-import {Directive} from '@angular/core';
-import {Location} from '@angular/common';
-import {isString} from '../../src/facade/lang';
-import {Router} from '../router';
-import {Instruction} from '../instruction';
+import {
+ ResolvedReflectiveProvider,
+ Directive,
+ DynamicComponentLoader,
+ ViewContainerRef,
+ Attribute,
+ ComponentRef,
+ ComponentFactory,
+ ReflectiveInjector,
+ OnInit,
+ HostListener,
+ HostBinding,
+ Input,
+ OnDestroy,
+ Optional
+} from '@angular/core';
+import {RouterOutletMap, Router} from '../router';
+import {RouteSegment, UrlSegment, Tree} from '../segments';
+import {isString, isPresent} from '@angular/facade/src/lang';
+import {ObservableWrapper} from '@angular/facade/src/async';
-/**
- * The RouterLink directive lets you link to specific parts of your app.
- *
- * Consider the following route configuration:
+@Directive({selector: '[routerLink]'})
+export class RouterLink implements OnDestroy {
+ @Input() target: string;
+ private _changes: any[] = [];
+ private _subscription: any;
- * ```
- * @RouteConfig([
- * { path: '/user', component: UserCmp, as: 'User' }
- * ]);
- * class MyComp {}
- * ```
- *
- * When linking to this `User` route, you can write:
- *
- * ```
- * link to user component
- * ```
- *
- * RouterLink expects the value to be an array of route names, followed by the params
- * for that level of routing. For instance `['/Team', {teamId: 1}, 'User', {userId: 2}]`
- * means that we want to generate a link for the `Team` route with params `{teamId: 1}`,
- * and with a child route `User` with params `{userId: 2}`.
- *
- * The first route name should be prepended with `/`, `./`, or `../`.
- * If the route begins with `/`, the router will look up the route from the root of the app.
- * If the route begins with `./`, the router will instead look in the current component's
- * children for the route. And if the route begins with `../`, the router will look at the
- * current component's parent.
- */
-@Directive({
- selector: '[routerLink]',
- inputs: ['routeParams: routerLink', 'target: target'],
- host: {
- '(click)': 'onClick()',
- '[attr.href]': 'visibleHref',
- '[class.router-link-active]': 'isRouteActive'
- }
-})
-export class RouterLink {
- private _routeParams: any[];
+ @HostBinding() private href: string;
+ @HostBinding('class.router-link-active') private isActive: boolean = false;
- // the url displayed on the anchor element.
- visibleHref: string;
- target: string;
-
- // the instruction passed to the router to navigate
- private _navigationInstruction: Instruction;
-
- constructor(private _router: Router, private _location: Location) {
- // we need to update the link whenever a route changes to account for aux routes
- this._router.subscribe((_) => this._updateLink());
+ constructor(@Optional() private _routeSegment: RouteSegment, private _router: Router) {
+ this._subscription =
+ ObservableWrapper.subscribe(_router.changes, (_) => { this._updateTargetUrlAndHref(); });
}
- // because auxiliary links take existing primary and auxiliary routes into account,
- // we need to update the link whenever params or other routes change.
- private _updateLink(): void {
- this._navigationInstruction = this._router.generate(this._routeParams);
- var navigationHref = this._navigationInstruction.toLinkUrl();
- this.visibleHref = this._location.prepareExternalUrl(navigationHref);
- }
-
- get isRouteActive(): boolean { return this._router.isRouteActive(this._navigationInstruction); }
-
- set routeParams(changes: any[]) {
- this._routeParams = changes;
- this._updateLink();
+ ngOnDestroy() { ObservableWrapper.dispose(this._subscription); }
+
+ @Input()
+ set routerLink(data: any[]) {
+ this._changes = data;
+ this._updateTargetUrlAndHref();
}
+ @HostListener("click")
onClick(): boolean {
- // If no target, or if target is _self, prevent default browser behavior
if (!isString(this.target) || this.target == '_self') {
- this._router.navigateByInstruction(this._navigationInstruction);
+ this._router.navigate(this._changes, this._routeSegment);
return false;
}
return true;
}
+
+ private _updateTargetUrlAndHref(): void {
+ let tree = this._router.createUrlTree(this._changes, this._routeSegment);
+ if (isPresent(tree)) {
+ this.href = this._router.serializeUrl(tree);
+ this.isActive = this._router.urlTree.contains(tree);
+ } else {
+ this.isActive = false;
+ }
+ }
}
diff --git a/modules/@angular/router/src/directives/router_outlet.ts b/modules/@angular/router/src/directives/router_outlet.ts
index f7279758fe..fbdb041d95 100644
--- a/modules/@angular/router/src/directives/router_outlet.ts
+++ b/modules/@angular/router/src/directives/router_outlet.ts
@@ -1,176 +1,42 @@
-import {PromiseWrapper, EventEmitter} from '../../src/facade/async';
-import {StringMapWrapper} from '../../src/facade/collection';
-import {isBlank, isPresent} from '../../src/facade/lang';
import {
+ ResolvedReflectiveProvider,
Directive,
- Attribute,
DynamicComponentLoader,
- ComponentRef,
ViewContainerRef,
- provide,
+ Attribute,
+ ComponentRef,
+ ComponentFactory,
ReflectiveInjector,
- OnDestroy,
- Output
+ OnInit
} from '@angular/core';
-import * as routerMod from '../router';
-import {ComponentInstruction, RouteParams, RouteData} from '../instruction';
-import * as hookMod from '../lifecycle/lifecycle_annotations';
-import {hasLifecycleHook} from '../lifecycle/route_lifecycle_reflector';
-import {OnActivate, CanReuse, OnReuse, OnDeactivate, CanDeactivate} from '../interfaces';
+import {RouterOutletMap} from '../router';
+import {DEFAULT_OUTLET_NAME} from '../constants';
+import {isPresent, isBlank} from '@angular/facade/src/lang';
-let _resolveToTrue = PromiseWrapper.resolve(true);
-
-/**
- * A router outlet is a placeholder that Angular dynamically fills based on the application's route.
- *
- * ## Use
- *
- * ```
- *
- * ```
- */
@Directive({selector: 'router-outlet'})
-export class RouterOutlet implements OnDestroy {
- name: string = null;
- private _componentRef: Promise> = null;
- private _currentInstruction: ComponentInstruction = null;
+export class RouterOutlet {
+ private _loaded: ComponentRef;
+ public outletMap: RouterOutletMap;
- @Output('activate') public activateEvents = new EventEmitter();
-
- constructor(private _viewContainerRef: ViewContainerRef, private _loader: DynamicComponentLoader,
- private _parentRouter: routerMod.Router, @Attribute('name') nameAttr: string) {
- if (isPresent(nameAttr)) {
- this.name = nameAttr;
- this._parentRouter.registerAuxOutlet(this);
- } else {
- this._parentRouter.registerPrimaryOutlet(this);
- }
+ constructor(parentOutletMap: RouterOutletMap, private _location: ViewContainerRef,
+ @Attribute('name') name: string) {
+ parentOutletMap.registerOutlet(isBlank(name) ? DEFAULT_OUTLET_NAME : name, this);
}
- /**
- * Called by the Router to instantiate a new component during the commit phase of a navigation.
- * This method in turn is responsible for calling the `routerOnActivate` hook of its child.
- */
- activate(nextInstruction: ComponentInstruction): Promise {
- var previousInstruction = this._currentInstruction;
- this._currentInstruction = nextInstruction;
- var componentType = nextInstruction.componentType;
- var childRouter = this._parentRouter.childRouter(componentType);
-
- var providers = ReflectiveInjector.resolve([
- provide(RouteData, {useValue: nextInstruction.routeData}),
- provide(RouteParams, {useValue: new RouteParams(nextInstruction.params)}),
- provide(routerMod.Router, {useValue: childRouter})
- ]);
- this._componentRef =
- this._loader.loadNextToLocation(componentType, this._viewContainerRef, providers);
- return this._componentRef.then((componentRef) => {
- this.activateEvents.emit(componentRef.instance);
- if (hasLifecycleHook(hookMod.routerOnActivate, componentType)) {
- return this._componentRef.then(
- (ref: ComponentRef) =>
- (ref.instance).routerOnActivate(nextInstruction, previousInstruction));
- } else {
- return componentRef;
- }
- });
+ unload(): void {
+ this._loaded.destroy();
+ this._loaded = null;
}
- /**
- * Called by the {@link Router} during the commit phase of a navigation when an outlet
- * reuses a component between different routes.
- * This method in turn is responsible for calling the `routerOnReuse` hook of its child.
- */
- reuse(nextInstruction: ComponentInstruction): Promise {
- var previousInstruction = this._currentInstruction;
- this._currentInstruction = nextInstruction;
+ get loadedComponent(): Object { return isPresent(this._loaded) ? this._loaded.instance : null; }
- // it's possible the component is removed before it can be reactivated (if nested withing
- // another dynamically loaded component, for instance). In that case, we simply activate
- // a new one.
- if (isBlank(this._componentRef)) {
- return this.activate(nextInstruction);
- } else {
- return PromiseWrapper.resolve(
- hasLifecycleHook(hookMod.routerOnReuse, this._currentInstruction.componentType) ?
- this._componentRef.then(
- (ref: ComponentRef) =>
- (ref.instance).routerOnReuse(nextInstruction, previousInstruction)) :
- true);
- }
+ get isLoaded(): boolean { return isPresent(this._loaded); }
+
+ load(factory: ComponentFactory, providers: ResolvedReflectiveProvider[],
+ outletMap: RouterOutletMap): ComponentRef {
+ this.outletMap = outletMap;
+ let inj = ReflectiveInjector.fromResolvedProviders(providers, this._location.parentInjector);
+ this._loaded = this._location.createComponent(factory, this._location.length, inj, []);
+ return this._loaded;
}
-
- /**
- * Called by the {@link Router} when an outlet disposes of a component's contents.
- * This method in turn is responsible for calling the `routerOnDeactivate` hook of its child.
- */
- deactivate(nextInstruction: ComponentInstruction): Promise {
- var next = _resolveToTrue;
- if (isPresent(this._componentRef) && isPresent(this._currentInstruction) &&
- hasLifecycleHook(hookMod.routerOnDeactivate, this._currentInstruction.componentType)) {
- next = this._componentRef.then(
- (ref: ComponentRef) =>
- (ref.instance)
- .routerOnDeactivate(nextInstruction, this._currentInstruction));
- }
- return next.then((_) => {
- if (isPresent(this._componentRef)) {
- var onDispose = this._componentRef.then((ref: ComponentRef) => ref.destroy());
- this._componentRef = null;
- return onDispose;
- }
- });
- }
-
- /**
- * Called by the {@link Router} during recognition phase of a navigation.
- *
- * If this resolves to `false`, the given navigation is cancelled.
- *
- * This method delegates to the child component's `routerCanDeactivate` hook if it exists,
- * and otherwise resolves to true.
- */
- routerCanDeactivate(nextInstruction: ComponentInstruction): Promise {
- if (isBlank(this._currentInstruction)) {
- return _resolveToTrue;
- }
- if (hasLifecycleHook(hookMod.routerCanDeactivate, this._currentInstruction.componentType)) {
- return this._componentRef.then(
- (ref: ComponentRef) =>
- (ref.instance)
- .routerCanDeactivate(nextInstruction, this._currentInstruction));
- } else {
- return _resolveToTrue;
- }
- }
-
- /**
- * Called by the {@link Router} during recognition phase of a navigation.
- *
- * If the new child component has a different Type than the existing child component,
- * this will resolve to `false`. You can't reuse an old component when the new component
- * is of a different Type.
- *
- * Otherwise, this method delegates to the child component's `routerCanReuse` hook if it exists,
- * or resolves to true if the hook is not present.
- */
- routerCanReuse(nextInstruction: ComponentInstruction): Promise {
- var result;
-
- if (isBlank(this._currentInstruction) ||
- this._currentInstruction.componentType != nextInstruction.componentType) {
- result = false;
- } else if (hasLifecycleHook(hookMod.routerCanReuse, this._currentInstruction.componentType)) {
- result = this._componentRef.then(
- (ref: ComponentRef) =>
- (ref.instance).routerCanReuse(nextInstruction, this._currentInstruction));
- } else {
- result = nextInstruction == this._currentInstruction ||
- (isPresent(nextInstruction.params) && isPresent(this._currentInstruction.params) &&
- StringMapWrapper.equals(nextInstruction.params, this._currentInstruction.params));
- }
- return >PromiseWrapper.resolve(result);
- }
-
- ngOnDestroy(): void { this._parentRouter.unregisterPrimaryOutlet(this); }
}
diff --git a/modules/@angular/router/src/interfaces.ts b/modules/@angular/router/src/interfaces.ts
index 1298448a0f..c09b38df5f 100644
--- a/modules/@angular/router/src/interfaces.ts
+++ b/modules/@angular/router/src/interfaces.ts
@@ -1,124 +1,10 @@
-import {ComponentInstruction} from './instruction';
-import {global} from '../src/facade/lang';
+import {RouteSegment, Tree, RouteTree} from './segments';
-// This is here only so that after TS transpilation the file is not empty.
-// TODO(rado): find a better way to fix this, or remove if likely culprit
-// https://github.com/systemjs/systemjs/issues/487 gets closed.
-var __ignore_me = global;
-var __make_dart_analyzer_happy: Promise = null;
-
-/**
- * Defines route lifecycle method `routerOnActivate`, which is called by the router at the end of a
- * successful route navigation.
- *
- * For a single component's navigation, only one of either {@link OnActivate} or {@link OnReuse}
- * will be called depending on the result of {@link CanReuse}.
- *
- * The `routerOnActivate` hook is called with two {@link ComponentInstruction}s as parameters, the
- * first
- * representing the current route being navigated to, and the second parameter representing the
- * previous route or `null`.
- *
- * If `routerOnActivate` returns a promise, the route change will wait until the promise settles to
- * instantiate and activate child components.
- *
- * ### Example
- * {@example router/ts/on_activate/on_activate_example.ts region='routerOnActivate'}
- */
export interface OnActivate {
- routerOnActivate(nextInstruction: ComponentInstruction,
- prevInstruction: ComponentInstruction): any |
- Promise;
+ routerOnActivate(curr: RouteSegment, prev?: RouteSegment, currTree?: RouteTree,
+ prevTree?: RouteTree): void;
}
-/**
- * Defines route lifecycle method `routerOnReuse`, which is called by the router at the end of a
- * successful route navigation when {@link CanReuse} is implemented and returns or resolves to true.
- *
- * For a single component's navigation, only one of either {@link OnActivate} or {@link OnReuse}
- * will be called, depending on the result of {@link CanReuse}.
- *
- * The `routerOnReuse` hook is called with two {@link ComponentInstruction}s as parameters, the
- * first
- * representing the current route being navigated to, and the second parameter representing the
- * previous route or `null`.
- *
- * ### Example
- * {@example router/ts/reuse/reuse_example.ts region='reuseCmp'}
- */
-export interface OnReuse {
- routerOnReuse(nextInstruction: ComponentInstruction, prevInstruction: ComponentInstruction): any |
- Promise;
-}
-
-/**
- * Defines route lifecycle method `routerOnDeactivate`, which is called by the router before
- * destroying
- * a component as part of a route change.
- *
- * The `routerOnDeactivate` hook is called with two {@link ComponentInstruction}s as parameters, the
- * first
- * representing the current route being navigated to, and the second parameter representing the
- * previous route.
- *
- * If `routerOnDeactivate` returns a promise, the route change will wait until the promise settles.
- *
- * ### Example
- * {@example router/ts/on_deactivate/on_deactivate_example.ts region='routerOnDeactivate'}
- */
-export interface OnDeactivate {
- routerOnDeactivate(nextInstruction: ComponentInstruction,
- prevInstruction: ComponentInstruction): any |
- Promise;
-}
-
-/**
- * Defines route lifecycle method `routerCanReuse`, which is called by the router to determine
- * whether a
- * component should be reused across routes, or whether to destroy and instantiate a new component.
- *
- * The `routerCanReuse` hook is called with two {@link ComponentInstruction}s as parameters, the
- * first
- * representing the current route being navigated to, and the second parameter representing the
- * previous route.
- *
- * If `routerCanReuse` returns or resolves to `true`, the component instance will be reused and the
- * {@link OnDeactivate} hook will be run. If `routerCanReuse` returns or resolves to `false`, a new
- * component will be instantiated, and the existing component will be deactivated and removed as
- * part of the navigation.
- *
- * If `routerCanReuse` throws or rejects, the navigation will be cancelled.
- *
- * ### Example
- * {@example router/ts/reuse/reuse_example.ts region='reuseCmp'}
- */
-export interface CanReuse {
- routerCanReuse(nextInstruction: ComponentInstruction,
- prevInstruction: ComponentInstruction): boolean |
- Promise;
-}
-
-/**
- * Defines route lifecycle method `routerCanDeactivate`, which is called by the router to determine
- * if a component can be removed as part of a navigation.
- *
- * The `routerCanDeactivate` hook is called with two {@link ComponentInstruction}s as parameters,
- * the
- * first representing the current route being navigated to, and the second parameter
- * representing the previous route.
- *
- * If `routerCanDeactivate` returns or resolves to `false`, the navigation is cancelled. If it
- * returns or
- * resolves to `true`, then the navigation continues, and the component will be deactivated
- * (the {@link OnDeactivate} hook will be run) and removed.
- *
- * If `routerCanDeactivate` throws or rejects, the navigation is also cancelled.
- *
- * ### Example
- * {@example router/ts/can_deactivate/can_deactivate_example.ts region='routerCanDeactivate'}
- */
export interface CanDeactivate {
- routerCanDeactivate(nextInstruction: ComponentInstruction,
- prevInstruction: ComponentInstruction): boolean |
- Promise;
-}
+ routerCanDeactivate(currTree?: RouteTree, futureTree?: RouteTree): Promise;
+}
\ No newline at end of file
diff --git a/modules/angular2/src/alt_router/lifecycle_reflector.dart b/modules/@angular/router/src/lifecycle_reflector.dart
similarity index 100%
rename from modules/angular2/src/alt_router/lifecycle_reflector.dart
rename to modules/@angular/router/src/lifecycle_reflector.dart
diff --git a/modules/angular2/src/alt_router/lifecycle_reflector.ts b/modules/@angular/router/src/lifecycle_reflector.ts
similarity index 100%
rename from modules/angular2/src/alt_router/lifecycle_reflector.ts
rename to modules/@angular/router/src/lifecycle_reflector.ts
diff --git a/modules/angular2/src/alt_router/link.ts b/modules/@angular/router/src/link.ts
similarity index 100%
rename from modules/angular2/src/alt_router/link.ts
rename to modules/@angular/router/src/link.ts
diff --git a/modules/angular2/src/alt_router/metadata/decorators.dart b/modules/@angular/router/src/metadata/decorators.dart
similarity index 100%
rename from modules/angular2/src/alt_router/metadata/decorators.dart
rename to modules/@angular/router/src/metadata/decorators.dart
diff --git a/modules/angular2/src/alt_router/metadata/decorators.ts b/modules/@angular/router/src/metadata/decorators.ts
similarity index 100%
rename from modules/angular2/src/alt_router/metadata/decorators.ts
rename to modules/@angular/router/src/metadata/decorators.ts
diff --git a/modules/angular2/src/alt_router/metadata/metadata.ts b/modules/@angular/router/src/metadata/metadata.ts
similarity index 100%
rename from modules/angular2/src/alt_router/metadata/metadata.ts
rename to modules/@angular/router/src/metadata/metadata.ts
diff --git a/modules/angular2/src/alt_router/recognize.ts b/modules/@angular/router/src/recognize.ts
similarity index 100%
rename from modules/angular2/src/alt_router/recognize.ts
rename to modules/@angular/router/src/recognize.ts
diff --git a/modules/@angular/router/src/router.ts b/modules/@angular/router/src/router.ts
index 7587686a21..2c5bc6751e 100644
--- a/modules/@angular/router/src/router.ts
+++ b/modules/@angular/router/src/router.ts
@@ -1,578 +1,226 @@
-import {PromiseWrapper, EventEmitter, ObservableWrapper} from '../src/facade/async';
-import {Map, StringMapWrapper} from '../src/facade/collection';
-import {isBlank, isPresent, Type} from '../src/facade/lang';
-import {BaseException} from '../src/facade/exceptions';
-import {Location} from '@angular/common';
-import {RouteRegistry, ROUTER_PRIMARY_COMPONENT} from './route_registry';
-import {ComponentInstruction, Instruction} from './instruction';
+import {OnInit, provide, ReflectiveInjector, ComponentResolver} from '@angular/core';
import {RouterOutlet} from './directives/router_outlet';
-import {getCanActivateHook} from './lifecycle/route_lifecycle_reflector';
-import {RouteDefinition} from './route_config/route_config_impl';
-import {Injectable, Inject} from '@angular/core';
+import {Type, isBlank, isPresent} from '@angular/facade/src/lang';
+import {ListWrapper} from '@angular/facade/src/collection';
+import {
+ EventEmitter,
+ Observable,
+ PromiseWrapper,
+ ObservableWrapper
+} from '@angular/facade/src/async';
+import {StringMapWrapper} from '@angular/facade/src/collection';
+import {BaseException} from '@angular/core';
+import {RouterUrlSerializer} from './router_url_serializer';
+import {CanDeactivate} from './interfaces';
+import {recognize} from './recognize';
+import {Location} from '@angular/common';
+import {link} from './link';
-let _resolveToTrue = PromiseWrapper.resolve(true);
-let _resolveToFalse = PromiseWrapper.resolve(false);
+import {
+ equalSegments,
+ routeSegmentComponentFactory,
+ RouteSegment,
+ UrlTree,
+ RouteTree,
+ rootNode,
+ TreeNode,
+ UrlSegment,
+ serializeRouteSegmentTree
+} from './segments';
+import {hasLifecycleHook} from './lifecycle_reflector';
+import {DEFAULT_OUTLET_NAME} from './constants';
+
+export class RouterOutletMap {
+ /** @internal */
+ _outlets: {[name: string]: RouterOutlet} = {};
+ registerOutlet(name: string, outlet: RouterOutlet): void { this._outlets[name] = outlet; }
+}
-/**
- * The `Router` is responsible for mapping URLs to components.
- *
- * You can see the state of the router by inspecting the read-only field `router.navigating`.
- * This may be useful for showing a spinner, for instance.
- *
- * ## Concepts
- *
- * Routers and component instances have a 1:1 correspondence.
- *
- * The router holds reference to a number of {@link RouterOutlet}.
- * An outlet is a placeholder that the router dynamically fills in depending on the current URL.
- *
- * When the router navigates from a URL, it must first recognize it and serialize it into an
- * `Instruction`.
- * The router uses the `RouteRegistry` to get an `Instruction`.
- */
-@Injectable()
export class Router {
- navigating: boolean = false;
- lastNavigationAttempt: string;
- /**
- * The current `Instruction` for the router
- */
- public currentInstruction: Instruction = null;
+ private _prevTree: RouteTree;
+ private _urlTree: UrlTree;
+ private _locationSubscription: any;
+ private _changes: EventEmitter = new EventEmitter();
- private _currentNavigation: Promise = _resolveToTrue;
- private _outlet: RouterOutlet = null;
-
- private _auxRouters = new Map();
- private _childRouter: Router;
-
- private _subject: EventEmitter = new EventEmitter();
-
-
- constructor(public registry: RouteRegistry, public parent: Router, public hostComponent: any,
- public root?: Router) {}
-
- /**
- * Constructs a child router. You probably don't need to use this unless you're writing a reusable
- * component.
- */
- childRouter(hostComponent: any): Router {
- return this._childRouter = new ChildRouter(this, hostComponent);
+ constructor(private _rootComponent: Object, private _rootComponentType: Type,
+ private _componentResolver: ComponentResolver,
+ private _urlSerializer: RouterUrlSerializer,
+ private _routerOutletMap: RouterOutletMap, private _location: Location) {
+ this._prevTree = this._createInitialTree();
+ this._setUpLocationChangeListener();
+ this.navigateByUrl(this._location.path());
}
+ get urlTree(): UrlTree { return this._urlTree; }
- /**
- * Constructs a child router. You probably don't need to use this unless you're writing a reusable
- * component.
- */
- auxRouter(hostComponent: any): Router { return new ChildRouter(this, hostComponent); }
-
- /**
- * Register an outlet to be notified of primary route changes.
- *
- * You probably don't need to use this unless you're writing a reusable component.
- */
- registerPrimaryOutlet(outlet: RouterOutlet): Promise {
- if (isPresent(outlet.name)) {
- throw new BaseException(`registerPrimaryOutlet expects to be called with an unnamed outlet.`);
- }
-
- if (isPresent(this._outlet)) {
- throw new BaseException(`Primary outlet is already registered.`);
- }
-
- this._outlet = outlet;
- if (isPresent(this.currentInstruction)) {
- return this.commit(this.currentInstruction, false);
- }
- return _resolveToTrue;
+ navigateByUrl(url: string): Promise {
+ return this._navigate(this._urlSerializer.parse(url));
}
- /**
- * Unregister an outlet (because it was destroyed, etc).
- *
- * You probably don't need to use this unless you're writing a custom outlet implementation.
- */
- unregisterPrimaryOutlet(outlet: RouterOutlet): void {
- if (isPresent(outlet.name)) {
- throw new BaseException(`registerPrimaryOutlet expects to be called with an unnamed outlet.`);
- }
- this._outlet = null;
+ navigate(changes: any[], segment?: RouteSegment): Promise {
+ return this._navigate(this.createUrlTree(changes, segment));
}
+ dispose(): void { ObservableWrapper.dispose(this._locationSubscription); }
- /**
- * Register an outlet to notified of auxiliary route changes.
- *
- * You probably don't need to use this unless you're writing a reusable component.
- */
- registerAuxOutlet(outlet: RouterOutlet): Promise {
- var outletName = outlet.name;
- if (isBlank(outletName)) {
- throw new BaseException(`registerAuxOutlet expects to be called with an outlet with a name.`);
- }
-
- var router = this.auxRouter(this.hostComponent);
-
- this._auxRouters.set(outletName, router);
- router._outlet = outlet;
-
- var auxInstruction;
- if (isPresent(this.currentInstruction) &&
- isPresent(auxInstruction = this.currentInstruction.auxInstruction[outletName])) {
- return router.commit(auxInstruction);
- }
- return _resolveToTrue;
+ private _createInitialTree(): RouteTree {
+ let root = new RouteSegment([new UrlSegment("", null, null)], null, DEFAULT_OUTLET_NAME,
+ this._rootComponentType, null);
+ return new RouteTree(new TreeNode(root, []));
}
-
- /**
- * Given an instruction, returns `true` if the instruction is currently active,
- * otherwise `false`.
- */
- isRouteActive(instruction: Instruction): boolean {
- var router: Router = this;
-
- if (isBlank(this.currentInstruction)) {
- return false;
- }
-
- // `instruction` corresponds to the root router
- while (isPresent(router.parent) && isPresent(instruction.child)) {
- router = router.parent;
- instruction = instruction.child;
- }
-
- if (isBlank(instruction.component) || isBlank(this.currentInstruction.component) ||
- this.currentInstruction.component.routeName != instruction.component.routeName) {
- return false;
- }
-
- let paramEquals = true;
-
- if (isPresent(this.currentInstruction.component.params)) {
- StringMapWrapper.forEach(instruction.component.params, (value, key) => {
- if (this.currentInstruction.component.params[key] !== value) {
- paramEquals = false;
- }
- });
- }
-
- return paramEquals;
+ private _setUpLocationChangeListener(): void {
+ this._locationSubscription = this._location.subscribe(
+ (change) => { this._navigate(this._urlSerializer.parse(change['url'])); });
}
-
- /**
- * Dynamically update the routing configuration and trigger a navigation.
- *
- * ### Usage
- *
- * ```
- * router.config([
- * { 'path': '/', 'component': IndexComp },
- * { 'path': '/user/:id', 'component': UserComp },
- * ]);
- * ```
- */
- config(definitions: RouteDefinition[]): Promise {
- definitions.forEach(
- (routeDefinition) => { this.registry.config(this.hostComponent, routeDefinition); });
- return this.renavigate();
- }
-
-
- /**
- * Navigate based on the provided Route Link DSL. It's preferred to navigate with this method
- * over `navigateByUrl`.
- *
- * ### Usage
- *
- * This method takes an array representing the Route Link DSL:
- * ```
- * ['./MyCmp', {param: 3}]
- * ```
- * See the {@link RouterLink} directive for more.
- */
- navigate(linkParams: any[]): Promise {
- var instruction = this.generate(linkParams);
- return this.navigateByInstruction(instruction, false);
- }
-
-
- /**
- * Navigate to a URL. Returns a promise that resolves when navigation is complete.
- * It's preferred to navigate with `navigate` instead of this method, since URLs are more brittle.
- *
- * If the given URL begins with a `/`, router will navigate absolutely.
- * If the given URL does not begin with `/`, the router will navigate relative to this component.
- */
- navigateByUrl(url: string, _skipLocationChange: boolean = false): Promise {
- return this._currentNavigation = this._currentNavigation.then((_) => {
- this.lastNavigationAttempt = url;
- this._startNavigating();
- return this._afterPromiseFinishNavigating(this.recognize(url).then((instruction) => {
- if (isBlank(instruction)) {
- return false;
- }
- return this._navigate(instruction, _skipLocationChange);
- }));
- });
- }
-
-
- /**
- * Navigate via the provided instruction. Returns a promise that resolves when navigation is
- * complete.
- */
- navigateByInstruction(instruction: Instruction,
- _skipLocationChange: boolean = false): Promise {
- if (isBlank(instruction)) {
- return _resolveToFalse;
- }
- return this._currentNavigation = this._currentNavigation.then((_) => {
- this._startNavigating();
- return this._afterPromiseFinishNavigating(this._navigate(instruction, _skipLocationChange));
- });
- }
-
- /** @internal */
- _settleInstruction(instruction: Instruction): Promise {
- return instruction.resolveComponent().then((_) => {
- var unsettledInstructions: Array> = [];
-
- if (isPresent(instruction.component)) {
- instruction.component.reuse = false;
- }
-
- if (isPresent(instruction.child)) {
- unsettledInstructions.push(this._settleInstruction(instruction.child));
- }
-
- StringMapWrapper.forEach(instruction.auxInstruction, (instruction: Instruction, _) => {
- unsettledInstructions.push(this._settleInstruction(instruction));
- });
- return PromiseWrapper.all(unsettledInstructions);
- });
- }
-
- /** @internal */
- _navigate(instruction: Instruction, _skipLocationChange: boolean): Promise {
- return this._settleInstruction(instruction)
- .then((_) => this._routerCanReuse(instruction))
- .then((_) => this._canActivate(instruction))
- .then((result: boolean) => {
- if (!result) {
- return false;
- }
- return this._routerCanDeactivate(instruction)
- .then((result: boolean) => {
- if (result) {
- return this.commit(instruction, _skipLocationChange)
- .then((_) => {
- this._emitNavigationFinish(instruction.toRootUrl());
- return true;
- });
+ private _navigate(url: UrlTree): Promise {
+ this._urlTree = url;
+ return recognize(this._componentResolver, this._rootComponentType, url)
+ .then(currTree => {
+ return new _LoadSegments(currTree, this._prevTree)
+ .load(this._routerOutletMap, this._rootComponent)
+ .then(updated => {
+ if (updated) {
+ this._prevTree = currTree;
+ this._location.go(this._urlSerializer.serialize(this._urlTree));
+ this._changes.emit(null);
}
});
});
}
- private _emitNavigationFinish(url): void { ObservableWrapper.callEmit(this._subject, url); }
- /** @internal */
- _emitNavigationFail(url): void { ObservableWrapper.callError(this._subject, url); }
-
- private _afterPromiseFinishNavigating(promise: Promise): Promise {
- return PromiseWrapper.catchError(promise.then((_) => this._finishNavigating()), (err) => {
- this._finishNavigating();
- throw err;
- });
- }
-
- /*
- * Recursively set reuse flags
- */
- /** @internal */
- _routerCanReuse(instruction: Instruction): Promise {
- if (isBlank(this._outlet)) {
- return _resolveToFalse;
- }
- if (isBlank(instruction.component)) {
- return _resolveToTrue;
- }
- return this._outlet.routerCanReuse(instruction.component)
- .then((result) => {
- instruction.component.reuse = result;
- if (result && isPresent(this._childRouter) && isPresent(instruction.child)) {
- return this._childRouter._routerCanReuse(instruction.child);
- }
- });
- }
-
- private _canActivate(nextInstruction: Instruction): Promise {
- return canActivateOne(nextInstruction, this.currentInstruction);
- }
-
- private _routerCanDeactivate(instruction: Instruction): Promise {
- if (isBlank(this._outlet)) {
- return _resolveToTrue;
- }
- var next: Promise;
- var childInstruction: Instruction = null;
- var reuse: boolean = false;
- var componentInstruction: ComponentInstruction = null;
- if (isPresent(instruction)) {
- childInstruction = instruction.child;
- componentInstruction = instruction.component;
- reuse = isBlank(instruction.component) || instruction.component.reuse;
- }
- if (reuse) {
- next = _resolveToTrue;
+ createUrlTree(changes: any[], segment?: RouteSegment): UrlTree {
+ if (isPresent(this._prevTree)) {
+ let s = isPresent(segment) ? segment : this._prevTree.root;
+ return link(s, this._prevTree, this.urlTree, changes);
} else {
- next = this._outlet.routerCanDeactivate(componentInstruction);
+ return null;
}
- // TODO: aux route lifecycle hooks
- return next.then((result): boolean | Promise => {
- if (result == false) {
- return false;
- }
- if (isPresent(this._childRouter)) {
- // TODO: ideally, this closure would map to async-await in Dart.
- // For now, casting to any to suppress an error.
- return this._childRouter._routerCanDeactivate(childInstruction);
- }
- return true;
- });
}
- /**
- * Updates this router and all descendant routers according to the given instruction
- */
- commit(instruction: Instruction, _skipLocationChange: boolean = false): Promise {
- this.currentInstruction = instruction;
+ serializeUrl(url: UrlTree): string { return this._urlSerializer.serialize(url); }
- var next: Promise = _resolveToTrue;
- if (isPresent(this._outlet) && isPresent(instruction.component)) {
- var componentInstruction = instruction.component;
- if (componentInstruction.reuse) {
- next = this._outlet.reuse(componentInstruction);
- } else {
- next =
- this.deactivate(instruction).then((_) => this._outlet.activate(componentInstruction));
- }
- if (isPresent(instruction.child)) {
- next = next.then((_) => {
- if (isPresent(this._childRouter)) {
- return this._childRouter.commit(instruction.child);
+ get changes(): Observable { return this._changes; }
+
+ get routeTree(): RouteTree { return this._prevTree; }
+}
+
+
+class _LoadSegments {
+ private deactivations: Object[][] = [];
+ private performMutation: boolean = true;
+
+ constructor(private currTree: RouteTree, private prevTree: RouteTree) {}
+
+ load(parentOutletMap: RouterOutletMap, rootComponent: Object): Promise {
+ let prevRoot = isPresent(this.prevTree) ? rootNode(this.prevTree) : null;
+ let currRoot = rootNode(this.currTree);
+
+ return this.canDeactivate(currRoot, prevRoot, parentOutletMap, rootComponent)
+ .then(res => {
+ this.performMutation = true;
+ if (res) {
+ this.loadChildSegments(currRoot, prevRoot, parentOutletMap, [rootComponent]);
}
+ return res;
});
- }
- }
+ }
- var promises: Promise[] = [];
- this._auxRouters.forEach((router, name) => {
- if (isPresent(instruction.auxInstruction[name])) {
- promises.push(router.commit(instruction.auxInstruction[name]));
- }
+ private canDeactivate(currRoot: TreeNode, prevRoot: TreeNode,
+ outletMap: RouterOutletMap, rootComponent: Object): Promise {
+ this.performMutation = false;
+ this.loadChildSegments(currRoot, prevRoot, outletMap, [rootComponent]);
+
+ let allPaths = PromiseWrapper.all(this.deactivations.map(r => this.checkCanDeactivatePath(r)));
+ return allPaths.then((values: boolean[]) => values.filter(v => v).length === values.length);
+ }
+
+ private checkCanDeactivatePath(path: Object[]): Promise {
+ let curr = PromiseWrapper.resolve(true);
+ for (let p of ListWrapper.reversed(path)) {
+ curr = curr.then(_ => {
+ if (hasLifecycleHook("routerCanDeactivate", p)) {
+ return (p).routerCanDeactivate(this.prevTree, this.currTree);
+ } else {
+ return _;
+ }
+ });
+ }
+ return curr;
+ }
+
+ private loadChildSegments(currNode: TreeNode, prevNode: TreeNode,
+ outletMap: RouterOutletMap, components: Object[]): void {
+ let prevChildren = isPresent(prevNode) ?
+ prevNode.children.reduce(
+ (m, c) => {
+ m[c.value.outlet] = c;
+ return m;
+ },
+ {}) :
+ {};
+
+ currNode.children.forEach(c => {
+ this.loadSegments(c, prevChildren[c.value.outlet], outletMap, components);
+ StringMapWrapper.delete(prevChildren, c.value.outlet);
});
- return next.then((_) => PromiseWrapper.all(promises));
+ StringMapWrapper.forEach(prevChildren,
+ (v, k) => this.unloadOutlet(outletMap._outlets[k], components));
}
+ loadSegments(currNode: TreeNode, prevNode: TreeNode,
+ parentOutletMap: RouterOutletMap, components: Object[]): void {
+ let curr = currNode.value;
+ let prev = isPresent(prevNode) ? prevNode.value : null;
+ let outlet = this.getOutlet(parentOutletMap, currNode.value);
- /** @internal */
- _startNavigating(): void { this.navigating = true; }
-
- /** @internal */
- _finishNavigating(): void { this.navigating = false; }
-
-
- /**
- * Subscribe to URL updates from the router
- */
- subscribe(onNext: (value: any) => void, onError?: (value: any) => void): Object {
- return ObservableWrapper.subscribe(this._subject, onNext, onError);
- }
-
-
- /**
- * Removes the contents of this router's outlet and all descendant outlets
- */
- deactivate(instruction: Instruction): Promise {
- var childInstruction: Instruction = null;
- var componentInstruction: ComponentInstruction = null;
- if (isPresent(instruction)) {
- childInstruction = instruction.child;
- componentInstruction = instruction.component;
+ if (equalSegments(curr, prev)) {
+ this.loadChildSegments(currNode, prevNode, outlet.outletMap,
+ components.concat([outlet.loadedComponent]));
+ } else {
+ this.unloadOutlet(outlet, components);
+ if (this.performMutation) {
+ let outletMap = new RouterOutletMap();
+ let loadedComponent = this.loadNewSegment(outletMap, curr, prev, outlet);
+ this.loadChildSegments(currNode, prevNode, outletMap, components.concat([loadedComponent]));
+ }
}
- var next: Promise = _resolveToTrue;
- if (isPresent(this._childRouter)) {
- next = this._childRouter.deactivate(childInstruction);
+ }
+
+ private loadNewSegment(outletMap: RouterOutletMap, curr: RouteSegment, prev: RouteSegment,
+ outlet: RouterOutlet): Object {
+ let resolved = ReflectiveInjector.resolve(
+ [provide(RouterOutletMap, {useValue: outletMap}), provide(RouteSegment, {useValue: curr})]);
+ let ref = outlet.load(routeSegmentComponentFactory(curr), resolved, outletMap);
+ if (hasLifecycleHook("routerOnActivate", ref.instance)) {
+ ref.instance.routerOnActivate(curr, prev, this.currTree, this.prevTree);
}
- if (isPresent(this._outlet)) {
- next = next.then((_) => this._outlet.deactivate(componentInstruction));
+ return ref.instance;
+ }
+
+ private getOutlet(outletMap: RouterOutletMap, segment: RouteSegment): RouterOutlet {
+ let outlet = outletMap._outlets[segment.outlet];
+ if (isBlank(outlet)) {
+ if (segment.outlet == DEFAULT_OUTLET_NAME) {
+ throw new BaseException(`Cannot find default outlet`);
+ } else {
+ throw new BaseException(`Cannot find the outlet ${segment.outlet}`);
+ }
}
-
- // TODO: handle aux routes
-
- return next;
+ return outlet;
}
-
- /**
- * Given a URL, returns an instruction representing the component graph
- */
- recognize(url: string): Promise {
- var ancestorComponents = this._getAncestorInstructions();
- return this.registry.recognize(url, ancestorComponents);
- }
-
- private _getAncestorInstructions(): Instruction[] {
- var ancestorInstructions: Instruction[] = [this.currentInstruction];
- var ancestorRouter: Router = this;
- while (isPresent(ancestorRouter = ancestorRouter.parent)) {
- ancestorInstructions.unshift(ancestorRouter.currentInstruction);
- }
- return ancestorInstructions;
- }
-
-
- /**
- * Navigates to either the last URL successfully navigated to, or the last URL requested if the
- * router has yet to successfully navigate.
- */
- renavigate(): Promise {
- if (isBlank(this.lastNavigationAttempt)) {
- return this._currentNavigation;
- }
- return this.navigateByUrl(this.lastNavigationAttempt);
- }
-
-
- /**
- * Generate an `Instruction` based on the provided Route Link DSL.
- */
- generate(linkParams: any[]): Instruction {
- var ancestorInstructions = this._getAncestorInstructions();
- return this.registry.generate(linkParams, ancestorInstructions);
- }
-}
-
-@Injectable()
-export class RootRouter extends Router {
- /** @internal */
- _location: Location;
- /** @internal */
- _locationSub: Object;
-
- constructor(registry: RouteRegistry, location: Location,
- @Inject(ROUTER_PRIMARY_COMPONENT) primaryComponent: Type) {
- super(registry, null, primaryComponent);
- this.root = this;
- this._location = location;
- this._locationSub = this._location.subscribe((change) => {
- // we call recognize ourselves
- this.recognize(change['url'])
- .then((instruction) => {
- if (isPresent(instruction)) {
- this.navigateByInstruction(instruction, isPresent(change['pop']))
- .then((_) => {
- // this is a popstate event; no need to change the URL
- if (isPresent(change['pop']) && change['type'] != 'hashchange') {
- return;
- }
- var emitPath = instruction.toUrlPath();
- var emitQuery = instruction.toUrlQuery();
- if (emitPath.length > 0 && emitPath[0] != '/') {
- emitPath = '/' + emitPath;
- }
-
- // We've opted to use pushstate and popState APIs regardless of whether you
- // an app uses HashLocationStrategy or PathLocationStrategy.
- // However, apps that are migrating might have hash links that operate outside
- // angular to which routing must respond.
- // Therefore we know that all hashchange events occur outside Angular.
- // To support these cases where we respond to hashchanges and redirect as a
- // result, we need to replace the top item on the stack.
- if (change['type'] == 'hashchange') {
- if (instruction.toRootUrl() != this._location.path()) {
- this._location.replaceState(emitPath, emitQuery);
- }
- } else {
- this._location.go(emitPath, emitQuery);
- }
- });
- } else {
- this._emitNavigationFail(change['url']);
- }
- });
- });
-
- this.registry.configFromComponent(primaryComponent);
- this.navigateByUrl(location.path());
- }
-
- commit(instruction: Instruction, _skipLocationChange: boolean = false): Promise {
- var emitPath = instruction.toUrlPath();
- var emitQuery = instruction.toUrlQuery();
- if (emitPath.length > 0 && emitPath[0] != '/') {
- emitPath = '/' + emitPath;
- }
- var promise = super.commit(instruction);
- if (!_skipLocationChange) {
- promise = promise.then((_) => { this._location.go(emitPath, emitQuery); });
- }
- return promise;
- }
-
- dispose(): void {
- if (isPresent(this._locationSub)) {
- ObservableWrapper.dispose(this._locationSub);
- this._locationSub = null;
+ private unloadOutlet(outlet: RouterOutlet, components: Object[]): void {
+ if (isPresent(outlet) && outlet.isLoaded) {
+ StringMapWrapper.forEach(outlet.outletMap._outlets,
+ (v, k) => this.unloadOutlet(v, components));
+ if (this.performMutation) {
+ outlet.unload();
+ } else {
+ this.deactivations.push(components.concat([outlet.loadedComponent]));
+ }
}
}
}
-
-class ChildRouter extends Router {
- constructor(parent: Router, hostComponent) {
- super(parent.registry, parent, hostComponent, parent.root);
- this.parent = parent;
- }
-
-
- navigateByUrl(url: string, _skipLocationChange: boolean = false): Promise {
- // Delegate navigation to the root router
- return this.parent.navigateByUrl(url, _skipLocationChange);
- }
-
- navigateByInstruction(instruction: Instruction,
- _skipLocationChange: boolean = false): Promise {
- // Delegate navigation to the root router
- return this.parent.navigateByInstruction(instruction, _skipLocationChange);
- }
-}
-
-
-function canActivateOne(nextInstruction: Instruction,
- prevInstruction: Instruction): Promise {
- var next = _resolveToTrue;
- if (isBlank(nextInstruction.component)) {
- return next;
- }
- if (isPresent(nextInstruction.child)) {
- next = canActivateOne(nextInstruction.child,
- isPresent(prevInstruction) ? prevInstruction.child : null);
- }
- return next.then((result: boolean): boolean => {
- if (result == false) {
- return false;
- }
- if (nextInstruction.component.reuse) {
- return true;
- }
- var hook = getCanActivateHook(nextInstruction.component.componentType);
- if (isPresent(hook)) {
- return hook(nextInstruction.component,
- isPresent(prevInstruction) ? prevInstruction.component : null);
- }
- return true;
- });
-}
diff --git a/modules/@angular/router/src/router_providers.ts b/modules/@angular/router/src/router_providers.ts
index baddb26ed0..1dfb6a3c7b 100644
--- a/modules/@angular/router/src/router_providers.ts
+++ b/modules/@angular/router/src/router_providers.ts
@@ -1,41 +1,8 @@
import {ROUTER_PROVIDERS_COMMON} from './router_providers_common';
-import {Provider} from '@angular/core';
import {BrowserPlatformLocation} from '@angular/platform-browser';
import {PlatformLocation} from '@angular/common';
-/**
- * A list of {@link Provider}s. To use the router, you must add this to your application.
- *
- * ### Example ([live demo](http://plnkr.co/edit/iRUP8B5OUbxCWQ3AcIDm))
- *
- * ```
- * import {Component} from '@angular/core';
- * import {
- * ROUTER_DIRECTIVES,
- * ROUTER_PROVIDERS,
- * RouteConfig
- * } from '@angular/router';
- *
- * @Component({directives: [ROUTER_DIRECTIVES]})
- * @RouteConfig([
- * {...},
- * ])
- * class AppCmp {
- * // ...
- * }
- *
- * bootstrap(AppCmp, [ROUTER_PROVIDERS]);
- * ```
- */
export const ROUTER_PROVIDERS: any[] = /*@ts2dart_const*/[
ROUTER_PROVIDERS_COMMON,
- /*@ts2dart_const*/ (
- /* @ts2dart_Provider */ {provide: PlatformLocation, useClass: BrowserPlatformLocation}),
+ /*@ts2dart_Provider*/ {provide: PlatformLocation, useClass: BrowserPlatformLocation},
];
-
-/**
- * Use {@link ROUTER_PROVIDERS} instead.
- *
- * @deprecated
- */
-export const ROUTER_BINDINGS = /*@ts2dart_const*/ ROUTER_PROVIDERS;
diff --git a/modules/@angular/router/src/router_providers_common.ts b/modules/@angular/router/src/router_providers_common.ts
index a9042754e1..b3822ef38c 100644
--- a/modules/@angular/router/src/router_providers_common.ts
+++ b/modules/@angular/router/src/router_providers_common.ts
@@ -1,39 +1,31 @@
-import {ApplicationRef, Provider} from '@angular/core';
+import {OpaqueToken, ComponentResolver} from '@angular/core';
import {LocationStrategy, PathLocationStrategy, Location} from '@angular/common';
-import {Router, RootRouter} from './router';
-import {RouteRegistry, ROUTER_PRIMARY_COMPONENT} from './route_registry';
-import {Type} from '../src/facade/lang';
-import {BaseException} from '../src/facade/exceptions';
+import {Router, RouterOutletMap} from './router';
+import {RouterUrlSerializer, DefaultRouterUrlSerializer} from './router_url_serializer';
+import {ApplicationRef} from '@angular/core';
+import {BaseException} from '@angular/core';
-/**
- * The Platform agnostic ROUTER PROVIDERS
- */
export const ROUTER_PROVIDERS_COMMON: any[] = /*@ts2dart_const*/[
- RouteRegistry,
- /* @ts2dart_Provider */ {provide: LocationStrategy, useClass: PathLocationStrategy},
- Location,
- {
+ RouterOutletMap,
+ /*@ts2dart_Provider*/ {provide: RouterUrlSerializer, useClass: DefaultRouterUrlSerializer},
+ /*@ts2dart_Provider*/ {provide: LocationStrategy, useClass: PathLocationStrategy}, Location,
+ /*@ts2dart_Provider*/ {
provide: Router,
useFactory: routerFactory,
- deps: [RouteRegistry, Location, ROUTER_PRIMARY_COMPONENT, ApplicationRef]
+ deps: /*@ts2dart_const*/
+ [ApplicationRef, ComponentResolver, RouterUrlSerializer, RouterOutletMap, Location],
},
- {
- provide: ROUTER_PRIMARY_COMPONENT,
- useFactory: routerPrimaryComponentFactory,
- deps: /*@ts2dart_const*/ ([ApplicationRef])
- }
];
-function routerFactory(registry: RouteRegistry, location: Location, primaryComponent: Type,
- appRef: ApplicationRef): RootRouter {
- var rootRouter = new RootRouter(registry, location, primaryComponent);
- appRef.registerDisposeListener(() => rootRouter.dispose());
- return rootRouter;
-}
-
-function routerPrimaryComponentFactory(app: ApplicationRef): Type {
+function routerFactory(app: ApplicationRef, componentResolver: ComponentResolver,
+ urlSerializer: RouterUrlSerializer, routerOutletMap: RouterOutletMap,
+ location: Location): Router {
if (app.componentTypes.length == 0) {
throw new BaseException("Bootstrap at least one component before injecting Router.");
}
- return app.componentTypes[0];
+ // TODO: vsavkin this should not be null
+ let router = new Router(null, app.componentTypes[0], componentResolver, urlSerializer,
+ routerOutletMap, location);
+ app.registerDisposeListener(() => router.dispose());
+ return router;
}
diff --git a/modules/angular2/src/alt_router/router_url_serializer.ts b/modules/@angular/router/src/router_url_serializer.ts
similarity index 100%
rename from modules/angular2/src/alt_router/router_url_serializer.ts
rename to modules/@angular/router/src/router_url_serializer.ts
diff --git a/modules/angular2/src/alt_router/segments.ts b/modules/@angular/router/src/segments.ts
similarity index 100%
rename from modules/angular2/src/alt_router/segments.ts
rename to modules/@angular/router/src/segments.ts
diff --git a/modules/angular2/test/alt_router/integration_spec.ts b/modules/@angular/router/test/integration_spec.ts
similarity index 100%
rename from modules/angular2/test/alt_router/integration_spec.ts
rename to modules/@angular/router/test/integration_spec.ts
diff --git a/modules/angular2/test/alt_router/link_spec.ts b/modules/@angular/router/test/link_spec.ts
similarity index 100%
rename from modules/angular2/test/alt_router/link_spec.ts
rename to modules/@angular/router/test/link_spec.ts
diff --git a/modules/angular2/test/alt_router/recognize_spec.ts b/modules/@angular/router/test/recognize_spec.ts
similarity index 100%
rename from modules/angular2/test/alt_router/recognize_spec.ts
rename to modules/@angular/router/test/recognize_spec.ts
diff --git a/modules/angular2/test/alt_router/router_url_serializer_spec.ts b/modules/@angular/router/test/router_url_serializer_spec.ts
similarity index 100%
rename from modules/angular2/test/alt_router/router_url_serializer_spec.ts
rename to modules/@angular/router/test/router_url_serializer_spec.ts
diff --git a/modules/angular2/test/alt_router/tree_spec.ts b/modules/@angular/router/test/tree_spec.ts
similarity index 100%
rename from modules/angular2/test/alt_router/tree_spec.ts
rename to modules/@angular/router/test/tree_spec.ts
diff --git a/modules/angular2/src/alt_router/router_testing_providers.ts b/modules/@angular/router/testing/router_testing_providers.ts
similarity index 100%
rename from modules/angular2/src/alt_router/router_testing_providers.ts
rename to modules/@angular/router/testing/router_testing_providers.ts
diff --git a/modules/angular2/alt_router.ts b/modules/angular2/alt_router.ts
deleted file mode 100644
index d7ea77a688..0000000000
--- a/modules/angular2/alt_router.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * @module
- * @description
- * Alternative implementation of the router. Experimental.
- */
-
-export {Router, RouterOutletMap} from './src/alt_router/router';
-export {RouteSegment, UrlSegment, Tree, UrlTree, RouteTree} from './src/alt_router/segments';
-export {Routes} from './src/alt_router/metadata/decorators';
-export {Route} from './src/alt_router/metadata/metadata';
-export {
- RouterUrlSerializer,
- DefaultRouterUrlSerializer
-} from './src/alt_router/router_url_serializer';
-export {OnActivate, CanDeactivate} from './src/alt_router/interfaces';
-export {ROUTER_PROVIDERS} from './src/alt_router/router_providers';
-
-import {RouterOutlet} from './src/alt_router/directives/router_outlet';
-import {RouterLink} from './src/alt_router/directives/router_link';
-
-export const ROUTER_DIRECTIVES: any[] = /*@ts2dart_const*/[RouterOutlet, RouterLink];
diff --git a/modules/angular2/src/alt_router/directives/router_link.ts b/modules/angular2/src/alt_router/directives/router_link.ts
deleted file mode 100644
index 8c662d3e38..0000000000
--- a/modules/angular2/src/alt_router/directives/router_link.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import {
- ResolvedReflectiveProvider,
- Directive,
- DynamicComponentLoader,
- ViewContainerRef,
- Attribute,
- ComponentRef,
- ComponentFactory,
- ReflectiveInjector,
- OnInit,
- HostListener,
- HostBinding,
- Input,
- OnDestroy,
- Optional
-} from '@angular/core';
-import {RouterOutletMap, Router} from '../router';
-import {RouteSegment, UrlSegment, Tree} from '../segments';
-import {isString, isPresent} from '@angular/facade/src/lang';
-import {ObservableWrapper} from '@angular/facade/src/async';
-
-@Directive({selector: '[routerLink]'})
-export class RouterLink implements OnDestroy {
- @Input() target: string;
- private _changes: any[] = [];
- private _subscription: any;
-
- @HostBinding() private href: string;
- @HostBinding('class.router-link-active') private isActive: boolean = false;
-
- constructor(@Optional() private _routeSegment: RouteSegment, private _router: Router) {
- this._subscription =
- ObservableWrapper.subscribe(_router.changes, (_) => { this._updateTargetUrlAndHref(); });
- }
-
- ngOnDestroy() { ObservableWrapper.dispose(this._subscription); }
-
- @Input()
- set routerLink(data: any[]) {
- this._changes = data;
- this._updateTargetUrlAndHref();
- }
-
- @HostListener("click")
- onClick(): boolean {
- if (!isString(this.target) || this.target == '_self') {
- this._router.navigate(this._changes, this._routeSegment);
- return false;
- }
- return true;
- }
-
- private _updateTargetUrlAndHref(): void {
- let tree = this._router.createUrlTree(this._changes, this._routeSegment);
- if (isPresent(tree)) {
- this.href = this._router.serializeUrl(tree);
- this.isActive = this._router.urlTree.contains(tree);
- } else {
- this.isActive = false;
- }
- }
-}
diff --git a/modules/angular2/src/alt_router/directives/router_outlet.ts b/modules/angular2/src/alt_router/directives/router_outlet.ts
deleted file mode 100644
index fbdb041d95..0000000000
--- a/modules/angular2/src/alt_router/directives/router_outlet.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import {
- ResolvedReflectiveProvider,
- Directive,
- DynamicComponentLoader,
- ViewContainerRef,
- Attribute,
- ComponentRef,
- ComponentFactory,
- ReflectiveInjector,
- OnInit
-} from '@angular/core';
-import {RouterOutletMap} from '../router';
-import {DEFAULT_OUTLET_NAME} from '../constants';
-import {isPresent, isBlank} from '@angular/facade/src/lang';
-
-@Directive({selector: 'router-outlet'})
-export class RouterOutlet {
- private _loaded: ComponentRef;
- public outletMap: RouterOutletMap;
-
- constructor(parentOutletMap: RouterOutletMap, private _location: ViewContainerRef,
- @Attribute('name') name: string) {
- parentOutletMap.registerOutlet(isBlank(name) ? DEFAULT_OUTLET_NAME : name, this);
- }
-
- unload(): void {
- this._loaded.destroy();
- this._loaded = null;
- }
-
- get loadedComponent(): Object { return isPresent(this._loaded) ? this._loaded.instance : null; }
-
- get isLoaded(): boolean { return isPresent(this._loaded); }
-
- load(factory: ComponentFactory, providers: ResolvedReflectiveProvider[],
- outletMap: RouterOutletMap): ComponentRef {
- this.outletMap = outletMap;
- let inj = ReflectiveInjector.fromResolvedProviders(providers, this._location.parentInjector);
- this._loaded = this._location.createComponent(factory, this._location.length, inj, []);
- return this._loaded;
- }
-}
diff --git a/modules/angular2/src/alt_router/interfaces.ts b/modules/angular2/src/alt_router/interfaces.ts
deleted file mode 100644
index c09b38df5f..0000000000
--- a/modules/angular2/src/alt_router/interfaces.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import {RouteSegment, Tree, RouteTree} from './segments';
-
-export interface OnActivate {
- routerOnActivate(curr: RouteSegment, prev?: RouteSegment, currTree?: RouteTree,
- prevTree?: RouteTree): void;
-}
-
-export interface CanDeactivate {
- routerCanDeactivate(currTree?: RouteTree, futureTree?: RouteTree): Promise;
-}
\ No newline at end of file
diff --git a/modules/angular2/src/alt_router/router.ts b/modules/angular2/src/alt_router/router.ts
deleted file mode 100644
index 2c5bc6751e..0000000000
--- a/modules/angular2/src/alt_router/router.ts
+++ /dev/null
@@ -1,226 +0,0 @@
-import {OnInit, provide, ReflectiveInjector, ComponentResolver} from '@angular/core';
-import {RouterOutlet} from './directives/router_outlet';
-import {Type, isBlank, isPresent} from '@angular/facade/src/lang';
-import {ListWrapper} from '@angular/facade/src/collection';
-import {
- EventEmitter,
- Observable,
- PromiseWrapper,
- ObservableWrapper
-} from '@angular/facade/src/async';
-import {StringMapWrapper} from '@angular/facade/src/collection';
-import {BaseException} from '@angular/core';
-import {RouterUrlSerializer} from './router_url_serializer';
-import {CanDeactivate} from './interfaces';
-import {recognize} from './recognize';
-import {Location} from '@angular/common';
-import {link} from './link';
-
-import {
- equalSegments,
- routeSegmentComponentFactory,
- RouteSegment,
- UrlTree,
- RouteTree,
- rootNode,
- TreeNode,
- UrlSegment,
- serializeRouteSegmentTree
-} from './segments';
-import {hasLifecycleHook} from './lifecycle_reflector';
-import {DEFAULT_OUTLET_NAME} from './constants';
-
-export class RouterOutletMap {
- /** @internal */
- _outlets: {[name: string]: RouterOutlet} = {};
- registerOutlet(name: string, outlet: RouterOutlet): void { this._outlets[name] = outlet; }
-}
-
-export class Router {
- private _prevTree: RouteTree;
- private _urlTree: UrlTree;
- private _locationSubscription: any;
- private _changes: EventEmitter = new EventEmitter();
-
- constructor(private _rootComponent: Object, private _rootComponentType: Type,
- private _componentResolver: ComponentResolver,
- private _urlSerializer: RouterUrlSerializer,
- private _routerOutletMap: RouterOutletMap, private _location: Location) {
- this._prevTree = this._createInitialTree();
- this._setUpLocationChangeListener();
- this.navigateByUrl(this._location.path());
- }
-
- get urlTree(): UrlTree { return this._urlTree; }
-
- navigateByUrl(url: string): Promise {
- return this._navigate(this._urlSerializer.parse(url));
- }
-
- navigate(changes: any[], segment?: RouteSegment): Promise {
- return this._navigate(this.createUrlTree(changes, segment));
- }
-
- dispose(): void { ObservableWrapper.dispose(this._locationSubscription); }
-
- private _createInitialTree(): RouteTree {
- let root = new RouteSegment([new UrlSegment("", null, null)], null, DEFAULT_OUTLET_NAME,
- this._rootComponentType, null);
- return new RouteTree(new TreeNode(root, []));
- }
-
- private _setUpLocationChangeListener(): void {
- this._locationSubscription = this._location.subscribe(
- (change) => { this._navigate(this._urlSerializer.parse(change['url'])); });
- }
-
- private _navigate(url: UrlTree): Promise {
- this._urlTree = url;
- return recognize(this._componentResolver, this._rootComponentType, url)
- .then(currTree => {
- return new _LoadSegments(currTree, this._prevTree)
- .load(this._routerOutletMap, this._rootComponent)
- .then(updated => {
- if (updated) {
- this._prevTree = currTree;
- this._location.go(this._urlSerializer.serialize(this._urlTree));
- this._changes.emit(null);
- }
- });
- });
- }
-
- createUrlTree(changes: any[], segment?: RouteSegment): UrlTree {
- if (isPresent(this._prevTree)) {
- let s = isPresent(segment) ? segment : this._prevTree.root;
- return link(s, this._prevTree, this.urlTree, changes);
- } else {
- return null;
- }
- }
-
- serializeUrl(url: UrlTree): string { return this._urlSerializer.serialize(url); }
-
- get changes(): Observable { return this._changes; }
-
- get routeTree(): RouteTree { return this._prevTree; }
-}
-
-
-class _LoadSegments {
- private deactivations: Object[][] = [];
- private performMutation: boolean = true;
-
- constructor(private currTree: RouteTree, private prevTree: RouteTree) {}
-
- load(parentOutletMap: RouterOutletMap, rootComponent: Object): Promise {
- let prevRoot = isPresent(this.prevTree) ? rootNode(this.prevTree) : null;
- let currRoot = rootNode(this.currTree);
-
- return this.canDeactivate(currRoot, prevRoot, parentOutletMap, rootComponent)
- .then(res => {
- this.performMutation = true;
- if (res) {
- this.loadChildSegments(currRoot, prevRoot, parentOutletMap, [rootComponent]);
- }
- return res;
- });
- }
-
- private canDeactivate(currRoot: TreeNode, prevRoot: TreeNode,
- outletMap: RouterOutletMap, rootComponent: Object): Promise {
- this.performMutation = false;
- this.loadChildSegments(currRoot, prevRoot, outletMap, [rootComponent]);
-
- let allPaths = PromiseWrapper.all(this.deactivations.map(r => this.checkCanDeactivatePath(r)));
- return allPaths.then((values: boolean[]) => values.filter(v => v).length === values.length);
- }
-
- private checkCanDeactivatePath(path: Object[]): Promise {
- let curr = PromiseWrapper.resolve(true);
- for (let p of ListWrapper.reversed(path)) {
- curr = curr.then(_ => {
- if (hasLifecycleHook("routerCanDeactivate", p)) {
- return (p).routerCanDeactivate(this.prevTree, this.currTree);
- } else {
- return _;
- }
- });
- }
- return curr;
- }
-
- private loadChildSegments(currNode: TreeNode, prevNode: TreeNode,
- outletMap: RouterOutletMap, components: Object[]): void {
- let prevChildren = isPresent(prevNode) ?
- prevNode.children.reduce(
- (m, c) => {
- m[c.value.outlet] = c;
- return m;
- },
- {}) :
- {};
-
- currNode.children.forEach(c => {
- this.loadSegments(c, prevChildren[c.value.outlet], outletMap, components);
- StringMapWrapper.delete(prevChildren, c.value.outlet);
- });
-
- StringMapWrapper.forEach(prevChildren,
- (v, k) => this.unloadOutlet(outletMap._outlets[k], components));
- }
-
- loadSegments(currNode: TreeNode, prevNode: TreeNode,
- parentOutletMap: RouterOutletMap, components: Object[]): void {
- let curr = currNode.value;
- let prev = isPresent(prevNode) ? prevNode.value : null;
- let outlet = this.getOutlet(parentOutletMap, currNode.value);
-
- if (equalSegments(curr, prev)) {
- this.loadChildSegments(currNode, prevNode, outlet.outletMap,
- components.concat([outlet.loadedComponent]));
- } else {
- this.unloadOutlet(outlet, components);
- if (this.performMutation) {
- let outletMap = new RouterOutletMap();
- let loadedComponent = this.loadNewSegment(outletMap, curr, prev, outlet);
- this.loadChildSegments(currNode, prevNode, outletMap, components.concat([loadedComponent]));
- }
- }
- }
-
- private loadNewSegment(outletMap: RouterOutletMap, curr: RouteSegment, prev: RouteSegment,
- outlet: RouterOutlet): Object {
- let resolved = ReflectiveInjector.resolve(
- [provide(RouterOutletMap, {useValue: outletMap}), provide(RouteSegment, {useValue: curr})]);
- let ref = outlet.load(routeSegmentComponentFactory(curr), resolved, outletMap);
- if (hasLifecycleHook("routerOnActivate", ref.instance)) {
- ref.instance.routerOnActivate(curr, prev, this.currTree, this.prevTree);
- }
- return ref.instance;
- }
-
- private getOutlet(outletMap: RouterOutletMap, segment: RouteSegment): RouterOutlet {
- let outlet = outletMap._outlets[segment.outlet];
- if (isBlank(outlet)) {
- if (segment.outlet == DEFAULT_OUTLET_NAME) {
- throw new BaseException(`Cannot find default outlet`);
- } else {
- throw new BaseException(`Cannot find the outlet ${segment.outlet}`);
- }
- }
- return outlet;
- }
-
- private unloadOutlet(outlet: RouterOutlet, components: Object[]): void {
- if (isPresent(outlet) && outlet.isLoaded) {
- StringMapWrapper.forEach(outlet.outletMap._outlets,
- (v, k) => this.unloadOutlet(v, components));
- if (this.performMutation) {
- outlet.unload();
- } else {
- this.deactivations.push(components.concat([outlet.loadedComponent]));
- }
- }
- }
-}
diff --git a/modules/angular2/src/alt_router/router_providers.ts b/modules/angular2/src/alt_router/router_providers.ts
deleted file mode 100644
index 1dfb6a3c7b..0000000000
--- a/modules/angular2/src/alt_router/router_providers.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import {ROUTER_PROVIDERS_COMMON} from './router_providers_common';
-import {BrowserPlatformLocation} from '@angular/platform-browser';
-import {PlatformLocation} from '@angular/common';
-
-export const ROUTER_PROVIDERS: any[] = /*@ts2dart_const*/[
- ROUTER_PROVIDERS_COMMON,
- /*@ts2dart_Provider*/ {provide: PlatformLocation, useClass: BrowserPlatformLocation},
-];
diff --git a/modules/angular2/src/alt_router/router_providers_common.ts b/modules/angular2/src/alt_router/router_providers_common.ts
deleted file mode 100644
index b3822ef38c..0000000000
--- a/modules/angular2/src/alt_router/router_providers_common.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import {OpaqueToken, ComponentResolver} from '@angular/core';
-import {LocationStrategy, PathLocationStrategy, Location} from '@angular/common';
-import {Router, RouterOutletMap} from './router';
-import {RouterUrlSerializer, DefaultRouterUrlSerializer} from './router_url_serializer';
-import {ApplicationRef} from '@angular/core';
-import {BaseException} from '@angular/core';
-
-export const ROUTER_PROVIDERS_COMMON: any[] = /*@ts2dart_const*/[
- RouterOutletMap,
- /*@ts2dart_Provider*/ {provide: RouterUrlSerializer, useClass: DefaultRouterUrlSerializer},
- /*@ts2dart_Provider*/ {provide: LocationStrategy, useClass: PathLocationStrategy}, Location,
- /*@ts2dart_Provider*/ {
- provide: Router,
- useFactory: routerFactory,
- deps: /*@ts2dart_const*/
- [ApplicationRef, ComponentResolver, RouterUrlSerializer, RouterOutletMap, Location],
- },
-];
-
-function routerFactory(app: ApplicationRef, componentResolver: ComponentResolver,
- urlSerializer: RouterUrlSerializer, routerOutletMap: RouterOutletMap,
- location: Location): Router {
- if (app.componentTypes.length == 0) {
- throw new BaseException("Bootstrap at least one component before injecting Router.");
- }
- // TODO: vsavkin this should not be null
- let router = new Router(null, app.componentTypes[0], componentResolver, urlSerializer,
- routerOutletMap, location);
- app.registerDisposeListener(() => router.dispose());
- return router;
-}
diff --git a/modules/angular2/src/core/di/provider_util.dart b/modules/angular2/src/core/di/provider_util.dart
deleted file mode 100644
index 9b83032815..0000000000
--- a/modules/angular2/src/core/di/provider_util.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-import './provider.dart' show Provider;
-
-bool isProviderLiteral(dynamic obj) {
- if (obj is Map) {
- Map map = obj as Map;
- return map.containsKey('provide');
- } else {
- return false;
- }
-}
-
-Provider createProvider(dynamic obj) {
- Map map = obj as Map;
- return new Provider(map['provide'], useClass: map['useClass'],
- useValue: map['useValue'],
- useExisting: map['useExisting'],
- useFactory: map['useFactory'],
- deps: map['deps'],
- multi: map['multi']);
-}
diff --git a/modules/angular2/src/core/di/provider_util.ts b/modules/angular2/src/core/di/provider_util.ts
deleted file mode 100644
index 0b22cdb6fb..0000000000
--- a/modules/angular2/src/core/di/provider_util.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import {Provider} from './provider';
-
-export function isProviderLiteral(obj: any): boolean {
- return obj && typeof obj == 'object' && obj.provide;
-}
-
-export function createProvider(obj: any): Provider {
- return new Provider(obj.provide, obj);
-}