X Tutup
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions modules/angular2/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ export const ROUTER_PROVIDERS: any[] = CONST_EXPR([
RouteRegistry,
CONST_EXPR(new Provider(LocationStrategy, {useClass: PathLocationStrategy})),
Location,
CONST_EXPR(
new Provider(Router,
{
useFactory: routerFactory,
deps: CONST_EXPR([RouteRegistry, Location, ROUTER_PRIMARY_COMPONENT])
})),
CONST_EXPR(new Provider(
Router,
{
useFactory: routerFactory,
deps: CONST_EXPR([RouteRegistry, Location, ROUTER_PRIMARY_COMPONENT, ApplicationRef])
})),
CONST_EXPR(new Provider(
ROUTER_PRIMARY_COMPONENT,
{useFactory: routerPrimaryComponentFactory, deps: CONST_EXPR([ApplicationRef])}))
Expand All @@ -129,8 +129,10 @@ export const ROUTER_PROVIDERS: any[] = CONST_EXPR([
*/
export const ROUTER_BINDINGS = ROUTER_PROVIDERS;

function routerFactory(registry, location, primaryComponent) {
return new RootRouter(registry, location, primaryComponent);
function routerFactory(registry, location, primaryComponent, appRef) {
var rootRouter = new RootRouter(registry, location, primaryComponent);
appRef.registerDisposeListener(() => rootRouter.dispose());
return rootRouter;
}

function routerPrimaryComponentFactory(app) {
Expand Down
18 changes: 18 additions & 0 deletions modules/angular2/src/core/application_ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ export function platformCommon(bindings?: Array<Type | Provider | any[]>, initia
* explicitly by calling {@link platform}().
*/
export abstract class PlatformRef {
/**
* Register a listener to be called when the platform is disposed.
*/
abstract registerDisposeListener(dispose: () => void): void;

/**
* Retrieve the platform {@link Injector}, which is the parent injector for
* every Angular application on the page and provides singleton providers.
Expand Down Expand Up @@ -210,9 +215,12 @@ export abstract class PlatformRef {
export class PlatformRef_ extends PlatformRef {
/** @internal */
_applications: ApplicationRef[] = [];
_disposeListeners: Function[] = [];

constructor(private _injector: Injector, private _dispose: () => void) { super(); }

registerDisposeListener(dispose: () => void): void { this._disposeListeners.push(dispose); }

get injector(): Injector { return this._injector; }

application(bindings: Array<Type | Provider | any[]>): ApplicationRef {
Expand Down Expand Up @@ -259,6 +267,7 @@ export class PlatformRef_ extends PlatformRef {

dispose(): void {
this._applications.forEach((app) => app.dispose());
this._disposeListeners.forEach((dispose) => dispose());
this._dispose();
}

Expand All @@ -278,6 +287,11 @@ export abstract class ApplicationRef {
*/
abstract registerBootstrapListener(listener: (ref: ComponentRef) => void): void;

/**
* Register a listener to be called when the application is disposed.
*/
abstract registerDisposeListener(dispose: () => void): void;

/**
* Bootstrap a new component at the root level of the application.
*
Expand Down Expand Up @@ -326,6 +340,7 @@ export abstract class ApplicationRef {

export class ApplicationRef_ extends ApplicationRef {
private _bootstrapListeners: Function[] = [];
private _disposeListeners: Function[] = [];
private _rootComponents: ComponentRef[] = [];
private _rootComponentTypes: Type[] = [];

Expand All @@ -337,6 +352,8 @@ export class ApplicationRef_ extends ApplicationRef {
this._bootstrapListeners.push(listener);
}

registerDisposeListener(dispose: () => void): void { this._disposeListeners.push(dispose); }

bootstrap(componentType: Type,
providers?: Array<Type | Provider | any[]>): Promise<ComponentRef> {
var completer = PromiseWrapper.completer();
Expand Down Expand Up @@ -380,6 +397,7 @@ export class ApplicationRef_ extends ApplicationRef {
dispose(): void {
// TODO(alxhub): Dispose of the NgZone.
this._rootComponents.forEach((ref) => ref.dispose());
this._disposeListeners.forEach((dispose) => dispose());
this._platform._applicationDisposed(this);
}

Expand Down
4 changes: 2 additions & 2 deletions modules/angular2/src/mock/location_mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ export class SpyLocation implements Location {
}

subscribe(onNext: (value: any) => void, onThrow: (error: any) => void = null,
onReturn: () => void = null) {
ObservableWrapper.subscribe(this._subject, onNext, onThrow, onReturn);
onReturn: () => void = null): Object {
return ObservableWrapper.subscribe(this._subject, onNext, onThrow, onReturn);
}

// TODO: remove these once Location is an interface, and can be implemented cleanly
Expand Down
24 changes: 24 additions & 0 deletions modules/angular2/src/mock/mock_application_ref.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {ApplicationRef} from 'angular2/src/core/application_ref';
import {Type} from 'angular2/src/core/facade/lang';
import {ComponentRef} from 'angular2/src/core/linker/dynamic_component_loader';
import {Provider, Injector} from 'angular2/src/core/di';
import {NgZone} from 'angular2/src/core/zone/ng_zone';
import {Promise} from 'angular2/src/core/facade/async';

export class MockApplicationRef extends ApplicationRef {
registerBootstrapListener(listener: (ref: ComponentRef) => void): void {}

registerDisposeListener(dispose: () => void): void {}

bootstrap(componentType: Type, bindings?: Array<Type | Provider | any[]>): Promise<ComponentRef> {
return null;
}

get injector(): Injector { return null; };

get zone(): NgZone { return null; };

dispose(): void {}

get componentTypes(): Type[] { return null; };
}
4 changes: 2 additions & 2 deletions modules/angular2/src/router/location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ export class Location {
* Subscribe to the platform's `popState` events.
*/
subscribe(onNext: (value: any) => void, onThrow: (exception: any) => void = null,
onReturn: () => void = null): void {
ObservableWrapper.subscribe(this._subject, onNext, onThrow, onReturn);
onReturn: () => void = null): Object {
return ObservableWrapper.subscribe(this._subject, onNext, onThrow, onReturn);
}
}

Expand Down
12 changes: 10 additions & 2 deletions modules/angular2/src/router/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -467,12 +467,13 @@ export class Router {
export class RootRouter extends Router {
/** @internal */
_location: Location;
_locationSub: Object;

constructor(registry: RouteRegistry, location: Location, primaryComponent: Type) {
super(registry, null, primaryComponent);
this._location = location;
this._location.subscribe((change) =>
this.navigateByUrl(change['url'], isPresent(change['pop'])));
this._locationSub = this._location.subscribe(
(change) => this.navigateByUrl(change['url'], isPresent(change['pop'])));
this.registry.configFromComponent(primaryComponent);
this.navigateByUrl(location.path());
}
Expand All @@ -489,6 +490,13 @@ export class RootRouter extends Router {
}
return promise;
}

dispose(): void {
if (isPresent(this._locationSub)) {
ObservableWrapper.dispose(this._locationSub);
this._locationSub = null;
}
}
}

class ChildRouter extends Router {
Expand Down
2 changes: 2 additions & 0 deletions modules/angular2/test/public_api_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ var NG_API = [
'ApplicationRef.bootstrap()',
'ApplicationRef.dispose()',
'ApplicationRef.registerBootstrapListener()',
'ApplicationRef.registerDisposeListener()',
*/
'AsyncPipe',
'AsyncPipe.onDestroy()',
Expand Down Expand Up @@ -865,6 +866,7 @@ var NG_API = [
'PlatformRef.application()',
'PlatformRef.asyncApplication()',
'PlatformRef.dispose()',
'PlatformRef.registerDisposeListener()',
*/
'PlatformRef.injector',
'Predicate:dart',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,17 @@ import {

import {LocationStrategy} from 'angular2/src/router/location_strategy';
import {MockLocationStrategy} from 'angular2/src/mock/mock_location_strategy';
import {ApplicationRef} from 'angular2/src/core/application_ref';
import {MockApplicationRef} from 'angular2/src/mock/mock_application_ref';

export function main() {
describe('router injectables', () => {
beforeEachBindings(() => {
return [ROUTER_PROVIDERS, provide(LocationStrategy, {useClass: MockLocationStrategy})];
return [
ROUTER_PROVIDERS,
provide(LocationStrategy, {useClass: MockLocationStrategy}),
provide(ApplicationRef, {useClass: MockApplicationRef})
];
});

// do not refactor out the `bootstrap` functionality. We still want to
Expand Down
X Tutup