9

Stupid question alert:

In our main app.module.ts file we set bootstrap parameter with value that defines our top-level component. So with this:

@NgModule({
  bootstrap: [AppComponent]
})

We tell that when our module is used, our top-level component is AppComponent. But why it is in array? Can there be more top-level components...?

6
  • github.com/angular/angular/blob/master/packages/core/src/… It is rendered in the same order as you declared it Commented Jun 29, 2017 at 9:58
  • @yurzui, thanks, I will delete question if no answer provided Commented Jun 29, 2017 at 9:59
  • 2
    I think there will be a lot of answers :) Commented Jun 29, 2017 at 10:00
  • @Maximus - thanks for the comprehensive answer. I will come back to this later, because now it makes no sense for me why should I use that fascinating feature :) Commented Jun 29, 2017 at 12:27
  • 1
    @Maximus - I am a zero now, but thanks a lot! :)) Commented Jun 29, 2017 at 13:24

2 Answers 2

11

Yes, Angular can have many top-level components. You can check it easily for yourself:

@Component({selector: 'a-comp', template: `A comp`})
export class AComp {}

@Component({selector: 'b-comp', template: `B comp`})
export class BComp {}


@NgModule({
  imports: [BrowserModule],
  declarations: [AComp, BComp],
  bootstrap: [AComp, BComp]
})
export class AppModule {
}

------------------

<body>
    <a-comp></a-comp>
    <b-comp></b-comp>
</body>

Under the hood mechanics

Angular will create two separate trees of views and attach both to the ApplicationRef here

PlatformRef_.prototype._moduleDoBootstrap = function (moduleRef) {
        var appRef = (moduleRef.injector.get(ApplicationRef));
        if (moduleRef._bootstrapComponents.length > 0) {
            moduleRef._bootstrapComponents.forEach(function (f) { return appRef.bootstrap(f); });
  --------------------------------

  // will be called two times
  ApplicationRef_.bootstrap = function (componentOrFactory, rootSelectorOrNode) {

  ...
  ApplicationRef.attachView(viewRef: ViewRef): void {
    const view = (viewRef as InternalViewRef);
    this._views.push(view);
    view.attachToAppRef(this);
  }

And then, when change detection will run applicationRef will go through these two views:

  ApplicationRef.tick(): void {
    ...
    try {
      this._views.forEach((view) => view.detectChanges());
      ...

Fascinating things

What's even more fascinating is that you can attach the <b-comp> to the application programatically without specifying the component BComponent in the module.boostrap: []:

export class AComponent {
  constructor(r: ComponentFactoryResolver, app: ApplicationRef) {
    const f = r.resolveComponentFactory(BComponent);
    app.bootstrap(f, 'b-comp');

---------------

@NgModule({
  imports: [BrowserModule],
  declarations: [AComponent, BComponent],
  entryComponents: [BComponent],
  bootstrap: [AppComponent]
})
export class AppModule {}

--------------

<body>
    <a-comp></a-comp>
    <b-comp></b-comp>
</body>
Sign up to request clarification or add additional context in comments.

1 Comment

Can we define an array and set that to "bootstrap" attribute, I was trying which give me following error Error: The module oa was bootstrapped, but it does not declare "@NgModule.bootstrap" components nor a "ngDoBootstrap" method. Please define one of these.
1

That's because you can bootstrap different modules to have different apps at the same time.

You can see this sample here:

Bootstrapping muliple components in Angular2

Which the important parts is:

@NgModule({
  imports: [],
  declarations: [App1, App2, App3],
  bootstrap: [App1, App2, App3]
})
export class BaseModule {}

<body>
   <app1>App1</app1>
  <app2>App1</app2>
  <app3>App1</app3>
</body>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.