refactor(core): introduce @NgModule.bootstrap and ngDoBootstrap method

If a `@NgModule` has a `bootstrap` property, `PlatformRef.bootstrapModule` /
`PlatformRef.bootstrapModuleFactory` will automatically bootstrap the components
listed in there.
If such a property does not exist, `PlatformRef.bootstrapModule` /
`PlatformRef.bootstrapModuleFactory` will try to call the method `ngDoBootstrap(appRef: ApplicationRef)` on the module class.
Otherwise an error is reported.
This commit is contained in:
Tobias Bosch
2016-08-02 06:54:08 -07:00
parent af2e80e068
commit 7e4fd7d7da
14 changed files with 156 additions and 37 deletions

View File

@ -633,6 +633,7 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier {
exportedPipes: CompilePipeMetadata[];
// Note: See CompileDirectiveMetadata.entryComponents why this has to be a type.
entryComponents: CompileTypeMetadata[];
bootstrapComponents: CompileTypeMetadata[];
providers: CompileProviderMetadata[];
importedModules: CompileNgModuleMetadata[];
@ -643,7 +644,8 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier {
constructor(
{type, providers, declaredDirectives, exportedDirectives, declaredPipes, exportedPipes,
entryComponents, importedModules, exportedModules, schemas, transitiveModule}: {
entryComponents, bootstrapComponents, importedModules, exportedModules, schemas,
transitiveModule}: {
type?: CompileTypeMetadata,
providers?:
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
@ -652,6 +654,7 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier {
declaredPipes?: CompilePipeMetadata[],
exportedPipes?: CompilePipeMetadata[],
entryComponents?: CompileTypeMetadata[],
bootstrapComponents?: CompileTypeMetadata[],
importedModules?: CompileNgModuleMetadata[],
exportedModules?: CompileNgModuleMetadata[],
transitiveModule?: TransitiveCompileNgModuleMetadata,
@ -664,6 +667,7 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier {
this.exportedPipes = _normalizeArray(exportedPipes);
this.providers = _normalizeArray(providers);
this.entryComponents = _normalizeArray(entryComponents);
this.bootstrapComponents = _normalizeArray(bootstrapComponents);
this.importedModules = _normalizeArray(importedModules);
this.exportedModules = _normalizeArray(exportedModules);
this.schemas = _normalizeArray(schemas);

View File

@ -237,6 +237,7 @@ export class CompileMetadataResolver {
const exportedModules: cpl.CompileNgModuleMetadata[] = [];
const providers: any[] = [];
const entryComponents: cpl.CompileTypeMetadata[] = [];
const bootstrapComponents: cpl.CompileTypeMetadata[] = [];
const schemas: SchemaMetadata[] = [];
if (meta.imports) {
@ -318,6 +319,12 @@ export class CompileMetadataResolver {
...flattenArray(meta.entryComponents)
.map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type))));
}
if (meta.bootstrap) {
bootstrapComponents.push(
...flattenArray(meta.bootstrap)
.map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type))));
}
entryComponents.push(...bootstrapComponents);
if (meta.schemas) {
schemas.push(...flattenArray(meta.schemas));
}
@ -329,6 +336,7 @@ export class CompileMetadataResolver {
type: this.getTypeMetadata(moduleType, staticTypeModuleUrl(moduleType)),
providers: providers,
entryComponents: entryComponents,
bootstrapComponents: bootstrapComponents,
schemas: schemas,
declaredDirectives: declaredDirectives,
exportedDirectives: exportedDirectives,

View File

@ -43,12 +43,18 @@ export class NgModuleCompiler {
new ParseLocation(sourceFile, null, null, null),
new ParseLocation(sourceFile, null, null, null));
var deps: ComponentFactoryDependency[] = [];
var entryComponents = ngModuleMeta.transitiveModule.entryComponents.map((entryComponent) => {
var id = new CompileIdentifierMetadata({name: entryComponent.name});
deps.push(new ComponentFactoryDependency(entryComponent, id));
return id;
});
var builder = new _InjectorBuilder(ngModuleMeta, entryComponents, sourceSpan);
var bootstrapComponentFactories: CompileIdentifierMetadata[] = [];
var entryComponentFactories =
ngModuleMeta.transitiveModule.entryComponents.map((entryComponent) => {
var id = new CompileIdentifierMetadata({name: entryComponent.name});
if (ngModuleMeta.bootstrapComponents.indexOf(entryComponent) > -1) {
bootstrapComponentFactories.push(id);
}
deps.push(new ComponentFactoryDependency(entryComponent, id));
return id;
});
var builder = new _InjectorBuilder(
ngModuleMeta, entryComponentFactories, bootstrapComponentFactories, sourceSpan);
var providerParser = new NgModuleProviderAnalyzer(ngModuleMeta, extraProviders, sourceSpan);
providerParser.parse().forEach((provider) => builder.addProvider(provider));
@ -78,8 +84,9 @@ class _InjectorBuilder {
constructor(
private _ngModuleMeta: CompileNgModuleMetadata,
private _entryComponents: CompileIdentifierMetadata[], private _sourceSpan: ParseSourceSpan) {
}
private _entryComponentFactories: CompileIdentifierMetadata[],
private _bootstrapComponentFactories: CompileIdentifierMetadata[],
private _sourceSpan: ParseSourceSpan) {}
addProvider(resolvedProvider: ProviderAst) {
var providerValueExpressions =
@ -125,8 +132,10 @@ class _InjectorBuilder {
[o.SUPER_EXPR
.callFn([
o.variable(InjectorProps.parent.name),
o.literalArr(
this._entryComponents.map((entryComponent) => o.importExpr(entryComponent)))
o.literalArr(this._entryComponentFactories.map(
(componentFactory) => o.importExpr(componentFactory))),
o.literalArr(this._bootstrapComponentFactories.map(
(componentFactory) => o.importExpr(componentFactory)))
])
.toStmt()]);