diff --git a/modules/angular2/core.dart b/modules/angular2/core.dart
index e7a55cc742..b768f15e16 100644
--- a/modules/angular2/core.dart
+++ b/modules/angular2/core.dart
@@ -9,6 +9,7 @@ export 'package:angular2/src/common/pipes.dart';
export 'package:angular2/src/facade/facade.dart';
export 'package:angular2/src/core/application_ref.dart'
hide ApplicationRef_, PlatformRef_;
+export 'package:angular2/src/core/application_tokens.dart' show APP_ID, APP_COMPONENT, APP_INITIALIZER, PLATFORM_INITIALIZER;
export 'package:angular2/src/core/linker.dart';
export 'package:angular2/src/core/zone.dart';
export 'package:angular2/src/core/render.dart';
diff --git a/modules/angular2/core.ts b/modules/angular2/core.ts
index 11aef8f54a..1c53a08007 100644
--- a/modules/angular2/core.ts
+++ b/modules/angular2/core.ts
@@ -10,7 +10,12 @@ export * from './src/common/pipes';
export * from './src/facade/facade';
export * from './src/core/linker';
export {platform, createNgZone, PlatformRef, ApplicationRef} from './src/core/application_ref';
-export {APP_ID, APP_COMPONENT} from './src/core/application_tokens';
+export {
+ APP_ID,
+ APP_COMPONENT,
+ APP_INITIALIZER,
+ PLATFORM_INITIALIZER
+} from './src/core/application_tokens';
export * from './src/core/zone';
export * from './src/core/render';
export * from './src/common/directives';
diff --git a/modules/angular2/platform/browser.ts b/modules/angular2/platform/browser.ts
index 7ca4bc4681..693e3804d5 100644
--- a/modules/angular2/platform/browser.ts
+++ b/modules/angular2/platform/browser.ts
@@ -13,8 +13,7 @@ import {Type, isPresent, CONST_EXPR} from 'angular2/src/facade/lang';
import {Promise} from 'angular2/src/facade/promise';
import {
BROWSER_PROVIDERS,
- BROWSER_APP_COMMON_PROVIDERS,
- initDomAdapter
+ BROWSER_APP_COMMON_PROVIDERS
} from 'angular2/src/platform/browser_common';
import {COMPILER_PROVIDERS} from 'angular2/compiler';
import {ComponentRef, platform, reflector} from 'angular2/core';
@@ -120,8 +119,6 @@ export function bootstrap(
appComponentType: Type,
customProviders?: Array): Promise {
reflector.reflectionCapabilities = new ReflectionCapabilities();
- initDomAdapter();
-
let appProviders =
isPresent(customProviders) ? [BROWSER_APP_PROVIDERS, customProviders] : BROWSER_APP_PROVIDERS;
return platform(BROWSER_PROVIDERS).application(appProviders).bootstrap(appComponentType);
diff --git a/modules/angular2/platform/browser_static.ts b/modules/angular2/platform/browser_static.ts
index bd6784301a..4ca014cc17 100644
--- a/modules/angular2/platform/browser_static.ts
+++ b/modules/angular2/platform/browser_static.ts
@@ -12,8 +12,7 @@ import {Type, isPresent, CONST_EXPR} from 'angular2/src/facade/lang';
import {Promise} from 'angular2/src/facade/promise';
import {
BROWSER_PROVIDERS,
- BROWSER_APP_COMMON_PROVIDERS,
- initDomAdapter
+ BROWSER_APP_COMMON_PROVIDERS
} from 'angular2/src/platform/browser_common';
import {ComponentRef, platform, reflector} from 'angular2/core';
@@ -31,7 +30,6 @@ export const BROWSER_APP_PROVIDERS: Array =
export function bootstrapStatic(appComponentType: Type,
customProviders?: Array,
initReflector?: Function): Promise {
- initDomAdapter();
if (isPresent(initReflector)) {
initReflector();
}
diff --git a/modules/angular2/src/core/application_ref.ts b/modules/angular2/src/core/application_ref.ts
index 48f1ed162b..1d37ec26d5 100644
--- a/modules/angular2/src/core/application_ref.ts
+++ b/modules/angular2/src/core/application_ref.ts
@@ -4,7 +4,9 @@ import {provide, Provider, Injector, OpaqueToken} from 'angular2/src/core/di';
import {
APP_COMPONENT_REF_PROMISE,
APP_COMPONENT,
- APP_ID_RANDOM_PROVIDER
+ APP_ID_RANDOM_PROVIDER,
+ PLATFORM_INITIALIZER,
+ APP_INITIALIZER
} from './application_tokens';
import {
Promise,
@@ -30,7 +32,6 @@ import {wtfLeave, wtfCreateScope, WtfScopeFn} from './profile/profile';
import {ChangeDetectorRef} from 'angular2/src/core/change_detection/change_detector_ref';
import {lockDevMode} from 'angular2/src/facade/lang';
-
/**
* Construct providers specific to an individual root component.
*/
@@ -103,15 +104,32 @@ export function platform(providers?: Array): PlatformRe
}
}
+/**
+ * Dispose the existing platform.
+ */
+export function disposePlatform(): void {
+ if (isPresent(_platform)) {
+ _platform.dispose();
+ _platform = null;
+ }
+}
+
function _createPlatform(providers?: Array): PlatformRef {
_platformProviders = providers;
- _platform = new PlatformRef_(Injector.resolveAndCreate(providers), () => {
+ let injector = Injector.resolveAndCreate(providers);
+ _platform = new PlatformRef_(injector, () => {
_platform = null;
_platformProviders = null;
});
+ _runPlatformInitializers(injector);
return _platform;
}
+function _runPlatformInitializers(injector: Injector): void {
+ let inits: Function[] = injector.getOptional(PLATFORM_INITIALIZER);
+ if (isPresent(inits)) inits.forEach(init => init());
+}
+
/**
* The Angular platform is the entry point for Angular on a web page. Each page
* has exactly one platform, and services (such as reflection) which are common
@@ -236,11 +254,12 @@ export class PlatformRef_ extends PlatformRef {
});
app = new ApplicationRef_(this, zone, injector);
this._applications.push(app);
+ _runAppInitializers(injector);
return app;
}
dispose(): void {
- this._applications.forEach((app) => app.dispose());
+ ListWrapper.clone(this._applications).forEach((app) => app.dispose());
this._disposeListeners.forEach((dispose) => dispose());
this._dispose();
}
@@ -249,6 +268,11 @@ export class PlatformRef_ extends PlatformRef {
_applicationDisposed(app: ApplicationRef): void { ListWrapper.remove(this._applications, app); }
}
+function _runAppInitializers(injector: Injector): void {
+ let inits: Function[] = injector.getOptional(APP_INITIALIZER);
+ if (isPresent(inits)) inits.forEach(init => init());
+}
+
/**
* A reference to an Angular application running on a page.
*
@@ -439,7 +463,7 @@ export class ApplicationRef_ extends ApplicationRef {
dispose(): void {
// TODO(alxhub): Dispose of the NgZone.
- this._rootComponents.forEach((ref) => ref.dispose());
+ ListWrapper.clone(this._rootComponents).forEach((ref) => ref.dispose());
this._disposeListeners.forEach((dispose) => dispose());
this._platform._applicationDisposed(this);
}
diff --git a/modules/angular2/src/core/application_tokens.ts b/modules/angular2/src/core/application_tokens.ts
index 809087cfbb..0a3780a44f 100644
--- a/modules/angular2/src/core/application_tokens.ts
+++ b/modules/angular2/src/core/application_tokens.ts
@@ -48,3 +48,14 @@ export const APP_ID_RANDOM_PROVIDER: Provider =
function _randomChar(): string {
return StringWrapper.fromCharCode(97 + Math.floor(Math.random() * 25));
}
+
+/**
+ * A function that will be executed when a platform is initialized.
+ */
+export const PLATFORM_INITIALIZER: OpaqueToken =
+ CONST_EXPR(new OpaqueToken("Platform Initializer"));
+
+/**
+ * A function that will be executed when an application is initialized.
+ */
+export const APP_INITIALIZER: OpaqueToken = CONST_EXPR(new OpaqueToken("Application Initializer"));
\ No newline at end of file
diff --git a/modules/angular2/src/platform/browser_common.ts b/modules/angular2/src/platform/browser_common.ts
index 41804d8eb4..8cf88c55f2 100644
--- a/modules/angular2/src/platform/browser_common.ts
+++ b/modules/angular2/src/platform/browser_common.ts
@@ -11,13 +11,13 @@ import {
reflector,
APPLICATION_COMMON_PROVIDERS,
PLATFORM_COMMON_PROVIDERS,
- EVENT_MANAGER_PLUGINS
+ EVENT_MANAGER_PLUGINS,
+ PLATFORM_INITIALIZER
} from "angular2/core";
import {COMMON_DIRECTIVES, COMMON_PIPES, FORM_PROVIDERS} from "angular2/common";
import {Renderer} from 'angular2/render';
import {Testability} from 'angular2/src/core/testability/testability';
-// TODO change these imports once dom_adapter is moved out of core
import {DOM} from 'angular2/src/core/dom/dom_adapter';
import {DomEventsPlugin} from 'angular2/src/platform/dom/events/dom_events';
import {KeyEventsPlugin} from 'angular2/src/platform/dom/events/key_events';
@@ -42,8 +42,10 @@ export {
export {By} from 'angular2/src/platform/browser/debug/by';
export {BrowserDomAdapter} from './browser/browser_adapter';
-export const BROWSER_PROVIDERS: Array =
- CONST_EXPR([PLATFORM_COMMON_PROVIDERS]);
+export const BROWSER_PROVIDERS: Array = CONST_EXPR([
+ PLATFORM_COMMON_PROVIDERS,
+ new Provider(PLATFORM_INITIALIZER, {useValue: initDomAdapter, multi: true}),
+]);
function _exceptionHandler(): ExceptionHandler {
return new ExceptionHandler(DOM, false);
@@ -73,7 +75,6 @@ export const BROWSER_APP_COMMON_PROVIDERS: Array {
var logger = new _ArrayLogger();
@@ -213,6 +218,23 @@ export function main() {
});
}));
+ it("should run platform initializers", inject([Log], (log: Log) => {
+ let p = platform([
+ BROWSER_PROVIDERS,
+ provide(PLATFORM_INITIALIZER, {useValue: log.fn("platform_init1"), multi: true}),
+ provide(PLATFORM_INITIALIZER, {useValue: log.fn("platform_init2"), multi: true})
+ ]);
+ expect(log.result()).toEqual("platform_init1; platform_init2");
+ log.clear();
+ p.application([
+ BROWSER_APP_PROVIDERS,
+ provide(APP_INITIALIZER, {useValue: log.fn("app_init1"), multi: true}),
+ provide(APP_INITIALIZER, {useValue: log.fn("app_init2"), multi: true})
+ ]);
+
+ expect(log.result()).toEqual("app_init1; app_init2");
+ }));
+
it('should register each application with the testability registry',
inject([AsyncTestCompleter], (async) => {
var refPromise1 = bootstrap(HelloRootCmp, testProviders);
diff --git a/modules/angular2/test/public_api_spec.ts b/modules/angular2/test/public_api_spec.ts
index c1cbc4b62a..3cc281ef35 100644
--- a/modules/angular2/test/public_api_spec.ts
+++ b/modules/angular2/test/public_api_spec.ts
@@ -27,6 +27,7 @@ import {SymbolsDiff} from './symbol_inspector/symbol_differ';
var NG_ALL = [
'APP_COMPONENT',
+ 'APP_INITIALIZER',
'APP_ID',
'AbstractProviderError',
'AbstractProviderError.addKey()',
@@ -1396,6 +1397,7 @@ var NG_ALL = [
'resolveForwardRef():js',
'wtfCreateScope():js',
'PLATFORM_COMMON_PROVIDERS',
+ 'PLATFORM_INITIALIZER',
'wtfCreateScope:dart',
'wtfEndTimeRange():js',
'wtfEndTimeRange:dart',