2015-04-17 09:59:56 -07:00
|
|
|
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
2015-05-14 13:01:48 -07:00
|
|
|
import {isBlank, isPresent} from 'angular2/src/facade/lang';
|
2015-04-17 09:59:56 -07:00
|
|
|
|
2015-05-29 14:58:41 -07:00
|
|
|
import {Directive, Attribute} from 'angular2/src/core/annotations/decorators';
|
2015-05-15 15:55:26 -07:00
|
|
|
import {DynamicComponentLoader, ComponentRef, ElementRef} from 'angular2/core';
|
2015-04-17 09:59:56 -07:00
|
|
|
import {Injector, bind} from 'angular2/di';
|
|
|
|
|
|
|
|
import * as routerMod from './router';
|
|
|
|
import {Instruction, RouteParams} from './instruction'
|
|
|
|
|
2015-05-14 13:01:48 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A router outlet is a placeholder that Angular dynamically fills based on the application's route.
|
|
|
|
*
|
|
|
|
* ## Use
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* <router-outlet></router-outlet>
|
|
|
|
* ```
|
|
|
|
*/
|
2015-04-30 13:38:40 -07:00
|
|
|
@Directive({
|
2015-04-17 09:59:56 -07:00
|
|
|
selector: 'router-outlet'
|
|
|
|
})
|
|
|
|
export class RouterOutlet {
|
2015-06-29 10:37:55 +02:00
|
|
|
private _childRouter: routerMod.Router = null;
|
|
|
|
private _componentRef: ComponentRef = null;
|
2015-05-29 14:58:41 -07:00
|
|
|
private _elementRef: ElementRef;
|
2015-06-29 10:37:55 +02:00
|
|
|
private _currentInstruction: Instruction = null;
|
2015-06-26 15:59:18 -07:00
|
|
|
private _injector: Injector;
|
2015-04-17 09:59:56 -07:00
|
|
|
|
2015-05-29 14:58:41 -07:00
|
|
|
constructor(elementRef: ElementRef, private _loader: DynamicComponentLoader,
|
2015-06-26 15:59:18 -07:00
|
|
|
private _parentRouter: routerMod.Router, _injector: Injector,
|
2015-05-29 14:58:41 -07:00
|
|
|
@Attribute('name') nameAttr: string) {
|
2015-05-21 13:59:14 -07:00
|
|
|
// TODO: reintroduce with new // sibling routes
|
|
|
|
// if (isBlank(nameAttr)) {
|
|
|
|
// nameAttr = 'default';
|
|
|
|
//}
|
2015-05-29 14:58:41 -07:00
|
|
|
|
2015-06-26 15:59:18 -07:00
|
|
|
this._injector = _injector.getAppInjector();
|
2015-05-15 15:55:26 -07:00
|
|
|
this._elementRef = elementRef;
|
2015-05-21 13:59:14 -07:00
|
|
|
this._parentRouter.registerOutlet(this);
|
2015-04-17 09:59:56 -07:00
|
|
|
}
|
|
|
|
|
2015-05-14 13:01:48 -07:00
|
|
|
/**
|
2015-05-21 13:59:14 -07:00
|
|
|
* Given an instruction, update the contents of this outlet.
|
2015-05-14 13:01:48 -07:00
|
|
|
*/
|
2015-05-29 14:58:41 -07:00
|
|
|
activate(instruction: Instruction): Promise<any> {
|
|
|
|
// if we're able to reuse the component, we just have to pass along the instruction to the
|
|
|
|
// component's router
|
2015-05-15 15:55:26 -07:00
|
|
|
// so it can propagate changes to its children
|
2015-05-21 13:59:14 -07:00
|
|
|
if ((instruction == this._currentInstruction || instruction.reuse) &&
|
|
|
|
isPresent(this._childRouter)) {
|
|
|
|
return this._childRouter.commit(instruction.child);
|
2015-05-14 13:01:48 -07:00
|
|
|
}
|
2015-04-17 09:59:56 -07:00
|
|
|
|
2015-05-19 10:35:28 -07:00
|
|
|
this._currentInstruction = instruction;
|
2015-05-15 15:55:26 -07:00
|
|
|
this._childRouter = this._parentRouter.childRouter(instruction.component);
|
|
|
|
var outletInjector = this._injector.resolveAndCreateChild([
|
2015-05-29 14:58:41 -07:00
|
|
|
bind(RouteParams)
|
2015-06-30 13:18:51 -07:00
|
|
|
.toValue(new RouteParams(instruction.params())),
|
2015-05-15 15:55:26 -07:00
|
|
|
bind(routerMod.Router).toValue(this._childRouter)
|
|
|
|
]);
|
|
|
|
|
2015-05-21 13:59:14 -07:00
|
|
|
return this.deactivate()
|
2015-06-16 09:45:03 -07:00
|
|
|
.then((_) => this._loader.loadNextToLocation(instruction.component, this._elementRef,
|
|
|
|
outletInjector))
|
2015-05-29 14:58:41 -07:00
|
|
|
.then((componentRef) => {
|
|
|
|
this._componentRef = componentRef;
|
2015-05-21 13:59:14 -07:00
|
|
|
return this._childRouter.commit(instruction.child);
|
2015-05-29 14:58:41 -07:00
|
|
|
});
|
2015-04-17 09:59:56 -07:00
|
|
|
}
|
|
|
|
|
2015-05-21 13:59:14 -07:00
|
|
|
|
2015-05-29 14:58:41 -07:00
|
|
|
deactivate(): Promise<any> {
|
|
|
|
return (isPresent(this._childRouter) ? this._childRouter.deactivate() :
|
|
|
|
PromiseWrapper.resolve(true))
|
2015-05-21 13:59:14 -07:00
|
|
|
.then((_) => {
|
|
|
|
if (isPresent(this._componentRef)) {
|
|
|
|
this._componentRef.dispose();
|
|
|
|
this._componentRef = null;
|
|
|
|
}
|
|
|
|
});
|
2015-04-17 09:59:56 -07:00
|
|
|
}
|
|
|
|
|
2015-05-29 14:58:41 -07:00
|
|
|
canDeactivate(instruction: Instruction): Promise<boolean> {
|
2015-05-14 13:01:48 -07:00
|
|
|
// TODO: how to get ahold of the component instance here?
|
2015-04-17 09:59:56 -07:00
|
|
|
return PromiseWrapper.resolve(true);
|
|
|
|
}
|
|
|
|
}
|