diff --git a/modules/angular2/router.js b/modules/angular2/router.js index a5118abcec..ddb3fa2662 100644 --- a/modules/angular2/router.js +++ b/modules/angular2/router.js @@ -18,7 +18,7 @@ import {Router, RootRouter} from './src/router/router'; import {RouteRegistry} from './src/router/route_registry'; import {Pipeline} from './src/router/pipeline'; import {Location} from './src/router/location'; -import {appComponentRefToken} from './src/core/application_tokens'; +import {appComponentTypeToken} from './src/core/application_tokens'; import {bind} from './di'; export var routerInjectables:List = [ @@ -26,7 +26,7 @@ export var routerInjectables:List = [ Pipeline, BrowserLocation, Location, - bind(Router).toFactory((registry, pipeline, location, app) => { - return new RootRouter(registry, pipeline, location, app.hostComponentType); - }, [RouteRegistry, Pipeline, Location, appComponentRefToken]) + bind(Router).toFactory((registry, pipeline, location, appRoot) => { + return new RootRouter(registry, pipeline, location, appRoot); + }, [RouteRegistry, Pipeline, Location, appComponentTypeToken]) ]; diff --git a/modules/angular2/src/core/application.js b/modules/angular2/src/core/application.js index 7e6133aa31..091361745f 100644 --- a/modules/angular2/src/core/application.js +++ b/modules/angular2/src/core/application.js @@ -39,7 +39,8 @@ import {DefaultDomCompiler} from 'angular2/src/render/dom/compiler/compiler'; import {internalView} from 'angular2/src/core/compiler/view_ref'; import { - appComponentRefToken + appComponentRefToken, + appComponentTypeToken } from './application_tokens'; var _rootInjector: Injector; @@ -53,6 +54,7 @@ var _rootBindings = [ function _injectorBindings(appComponentType): List { return [ bind(DOCUMENT_TOKEN).toValue(DOM.defaultDoc()), + bind(appComponentTypeToken).toValue(appComponentType), bind(appComponentRefToken).toAsyncFactory((dynamicComponentLoader, injector, testability, registry) => { diff --git a/modules/angular2/src/core/application_tokens.js b/modules/angular2/src/core/application_tokens.js index 417927506b..be03fa38ff 100644 --- a/modules/angular2/src/core/application_tokens.js +++ b/modules/angular2/src/core/application_tokens.js @@ -1,3 +1,4 @@ import {OpaqueToken} from 'angular2/di'; export var appComponentRefToken:OpaqueToken = new OpaqueToken('ComponentRef'); +export var appComponentTypeToken:OpaqueToken = new OpaqueToken('RootComponent'); diff --git a/modules/angular2/src/router/router_outlet.js b/modules/angular2/src/router/router_outlet.js index 09c8491443..e67851c489 100644 --- a/modules/angular2/src/router/router_outlet.js +++ b/modules/angular2/src/router/router_outlet.js @@ -37,6 +37,7 @@ export class RouterOutlet { _loader:DynamicComponentLoader; _componentRef:ComponentRef; _elementRef:ElementRef; + _currentInstruction:Instruction; constructor(elementRef:ElementRef, loader:DynamicComponentLoader, router:routerMod.Router, injector:Injector, @Attribute('name') nameAttr:String) { if (isBlank(nameAttr)) { @@ -49,6 +50,7 @@ export class RouterOutlet { this._childRouter = null; this._componentRef = null; + this._currentInstruction = null; this._parentRouter.registerOutlet(this, nameAttr); } @@ -58,10 +60,11 @@ export class RouterOutlet { activate(instruction:Instruction): Promise { // if we're able to reuse the component, we just have to pass along the instruction to the component's router // so it can propagate changes to its children - if (instruction.reuse && isPresent(this._childRouter)) { + if ((instruction == this._currentInstruction) || instruction.reuse && isPresent(this._childRouter)) { return this._childRouter.commit(instruction); } + this._currentInstruction = instruction; this._childRouter = this._parentRouter.childRouter(instruction.component); var outletInjector = this._injector.resolveAndCreateChild([ bind(RouteParams).toValue(new RouteParams(instruction.params)), @@ -71,6 +74,7 @@ export class RouterOutlet { if (isPresent(this._componentRef)) { this._componentRef.dispose(); } + return this._loader.loadNextToExistingLocation(instruction.component, this._elementRef, outletInjector).then((componentRef) => { this._componentRef = componentRef; return this._childRouter.commit(instruction); diff --git a/modules/angular2/test/router/router_integration_spec.js b/modules/angular2/test/router/router_integration_spec.js new file mode 100644 index 0000000000..53a13b6f36 --- /dev/null +++ b/modules/angular2/test/router/router_integration_spec.js @@ -0,0 +1,78 @@ +import { + AsyncTestCompleter, + beforeEach, + ddescribe, + describe, + expect, + iit, + inject, + it, + xdescribe, + xit, + } from 'angular2/test_lib'; + +import {bootstrap} from 'angular2/src/core/application'; +import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations'; +import {DOM} from 'angular2/src/dom/dom_adapter'; +import {bind} from 'angular2/di'; +import {View} from 'angular2/src/core/annotations_impl/view'; +import {DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer'; +import {RouteConfig} from 'angular2/src/router/route_config_impl'; +import {routerInjectables, Router, RouteParams, RouterOutlet} from 'angular2/router'; +import {SpyLocation} from 'angular2/src/mock/location_mock'; +import {Location} from 'angular2/src/router/location'; + +export function main() { + describe('router injectables', () => { + var fakeDoc, el, testBindings; + beforeEach(() => { + fakeDoc = DOM.createHtmlDocument(); + el = DOM.createElement('app-cmp', fakeDoc); + DOM.appendChild(fakeDoc.body, el); + testBindings = [ + routerInjectables, + bind(Location).toClass(SpyLocation), + bind(DOCUMENT_TOKEN).toValue(fakeDoc) + ]; + }); + + it('should support bootstrap a simple app', inject([AsyncTestCompleter], (async) => { + bootstrap(AppCmp, testBindings).then((applicationRef) => { + var router = applicationRef.hostComponent.router; + router.subscribe((_) => { + expect(el).toHaveText('outer { hello }'); + async.done(); + }); + }); + })); + + //TODO: add a test in which the child component has bindings + }); +} + + +@Component({ + selector: 'hello-cmp' +}) +@View({ + template: "hello" +}) +class HelloCmp {} + + +@Component({ + selector: 'app-cmp' +}) +@View({ + template: "outer { }", + directives: [RouterOutlet] +}) +@RouteConfig([{ + path: '/', component: HelloCmp +}]) +class AppCmp { + router:Router; + constructor(router:Router) { + this.router = router; + } +}