diff --git a/aio/content/guide/bootstrapping.md b/aio/content/guide/bootstrapping.md index d4b24442ae..3b3974fc41 100644 --- a/aio/content/guide/bootstrapping.md +++ b/aio/content/guide/bootstrapping.md @@ -165,7 +165,10 @@ most applications have only one component tree and bootstrap a single root compo This one root component is usually called `AppComponent` and is in the root module's `bootstrap` array. - +In a situation where you want to bootstrap a component based on an API response, +or you want to mount the `AppComponent` in a different DOM node that doesn't match +the component selector, please refer to `ApplicationRef.bootstrap()` +documentation. ## More about Angular Modules diff --git a/packages/core/src/application_ref.ts b/packages/core/src/application_ref.ts index 40d6bf6591..c08827237f 100644 --- a/packages/core/src/application_ref.ts +++ b/packages/core/src/application_ref.ts @@ -682,20 +682,41 @@ export class ApplicationRef { } /** - * Bootstrap a new component at the root level of the application. + * Bootstrap a component onto the element identified by its selector or, optionally, to a + * specified element. * * @usageNotes * ### Bootstrap process * - * When bootstrapping a new root component into an application, Angular mounts the - * specified application component onto DOM elements identified by the componentType's - * selector and kicks off automatic change detection to finish initializing the component. + * When bootstrapping a component, Angular mounts it onto a target DOM element + * and kicks off automatic change detection. The target DOM element can be + * provided using the `rootSelectorOrNode` argument. * - * Optionally, a component can be mounted onto a DOM element that does not match the - * componentType's selector. + * If the target DOM element is not provided, Angular tries to find one on a page + * using the `selector` of the component that is being bootstrapped + * (first matched element is used). * * ### Example - * {@example core/ts/platform/platform.ts region='longform'} + * + * Generally, we define the component to bootstrap in the `bootstrap` array of `NgModule`, + * but it requires us to know the component while writing the application code. + * + * Imagine a situation where we have to wait for an API call to decide about the component to + * bootstrap. We can use the `ngDoBootstrap` hook of the `NgModule` and call this method to + * dynamically bootstrap a component. + * + * {@example core/ts/platform/platform.ts region='componentSelector'} + * + * Optionally, a component can be mounted onto a DOM element that does not match the + * selector of the bootstrapped component. + * + * In the following example, we are providing a CSS selector to match the target element. + * + * {@example core/ts/platform/platform.ts region='cssSelector'} + * + * While in this example, we are providing reference to a DOM node. + * + * {@example core/ts/platform/platform.ts region='domNode'} */ bootstrap(componentOrFactory: ComponentFactory|Type, rootSelectorOrNode?: string|any): ComponentRef { diff --git a/packages/core/src/metadata/do_boostrap.ts b/packages/core/src/metadata/do_boostrap.ts index 09c1614afb..39921b3c34 100644 --- a/packages/core/src/metadata/do_boostrap.ts +++ b/packages/core/src/metadata/do_boostrap.ts @@ -19,6 +19,9 @@ import {ApplicationRef} from '../application_ref'; * See ["Bootstrapping"](guide/bootstrapping) and ["Entry components"](guide/entry-components). * * @usageNotes + * The example below uses `ApplicationRef.bootstrap()` to render the + * `AppComponent` on the page. + * * ```typescript * class AppModule implements DoBootstrap { * ngDoBootstrap(appRef: ApplicationRef) { diff --git a/packages/examples/core/ts/platform/platform.ts b/packages/examples/core/ts/platform/platform.ts index 38d7a13c95..3b3a01e8a0 100644 --- a/packages/examples/core/ts/platform/platform.ts +++ b/packages/examples/core/ts/platform/platform.ts @@ -6,14 +6,75 @@ * found in the LICENSE file at https://angular.io/license */ -import {Component, createPlatformFactory} from '@angular/core'; -import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; +import {ApplicationRef, Component, DoBootstrap, NgModule, Type} from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; -// #docregion longform -@Component({selector: 'app-root', template: 'Hello World'}) -class MyApp { +@Component({ + selector: 'app-root', + template: `

Component One

`, +}) +export class ComponentOne { } -const myPlatformFactory = createPlatformFactory(platformBrowserDynamic, 'myPlatform'); -myPlatformFactory().bootstrapModule(MyApp); -// #enddocregion +@Component({ + selector: 'app-root', + template: `

Component Two

`, +}) +export class ComponentTwo { +} + +@Component({ + selector: 'app-root', + template: `

Component Three

`, +}) +export class ComponentThree { +} + +@Component({ + selector: 'app-root', + template: `

Component Four

`, +}) +export class ComponentFour { +} + +@NgModule({imports: [BrowserModule], declarations: [ComponentOne, ComponentTwo]}) +export class AppModule implements DoBootstrap { + // #docregion componentSelector + ngDoBootstrap(appRef: ApplicationRef) { + this.fetchDataFromApi().then((componentName: string) => { + if (componentName === 'ComponentOne') { + appRef.bootstrap(ComponentOne); + } else { + appRef.bootstrap(ComponentTwo); + } + }); + } + // #enddocregion + + fetchDataFromApi(): Promise { + return new Promise((resolve) => { + setTimeout(() => { + resolve('ComponentTwo'); + }, 2000); + }); + } +} + +@NgModule({imports: [BrowserModule], declarations: [ComponentThree]}) +export class AppModuleTwo implements DoBootstrap { + // #docregion cssSelector + ngDoBootstrap(appRef: ApplicationRef) { + appRef.bootstrap(ComponentThree, '#root-element'); + } + // #enddocregion cssSelector +} + +@NgModule({imports: [BrowserModule], declarations: [ComponentFour]}) +export class AppModuleThree implements DoBootstrap { + // #docregion domNode + ngDoBootstrap(appRef: ApplicationRef) { + const element = document.querySelector('#root-element'); + appRef.bootstrap(ComponentFour, element); + } + // #enddocregion domNode +}