6

I have a fork of a preexisting, mature, non-Angular web app. I also have some existing Angular 2 components from a separate app that I wish to reuse. I would like to sprinkle the existing Angular components into the non-Angular app in various places. I would like to know if this is possible and advisable. Note that this is similar but not identical to Sprinkling Angular 2 components inside a non-angular page . I have a more specific scenario that I describe below.

Currently, I have figured out how to add single instances of these Angular components by bootstrapping a module that wraps my desired component. E.g. if I want to insert AppComponent into my existing non-Angular app:

In app.module.ts:

@NgModule({
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule { }

In app.component.ts:

@Component({
  selector: 'my-app'
  template: '<span>{{value}}</span>'
  ...
})
export class AppComponent { 
   public value: string;
   ...
 }

Whenever I want an AppComponent, I simply append a my-app element and bootstrap the module as follows:

platformBrowserDynamic().bootstrapModule(AppModule);

This works perfectly fine and gives the exact results I want for a single instance of AppComponent. However, my use cases require that I have two simultaneous instances of AppComponent in separate places of the DOM. If I attempt to bootstrap AppModule a second time, the core Angular code attaches the second AppModule to the my-app element that appears first in the DOM, effectively erasing my first instance of AppModule. Is there a way to tell Angular which my-app element to append to? Or is there any way around this?

HTML Example:

Let's say I append a <my-app> to <body>. Then my HTML looks like:

<body>
  <my-app>
  </my-app>
</body>

Next, if I call platformBrowserDynamic().bootstrapModule(AppModule); and set value = '111' anywhere in the AppComponent, my HTML looks like:

<body>
  <my-app>
    <span>111</span>
  </my-app>
</body>

Then I add another my-app selector to the HTML, so it looks like:

<body>
  <my-app>
    <span>111</span>
  </my-app>
  <my-app>
  </my-app>
</body>

Then, if I call platformBrowserDynamic().bootstrapModule(AppModule); and set value = '222' in the newly created AppComponenet anywhere in the AppComponent logic my HTML looks like:

<body>
  <my-app>
    <span>222</span>
  </my-app>
  <my-app>
  </my-app>
</body>

when I would like the desired result to be:

<body>
  <my-app>
    <span>111</span>
  </my-app>
  <my-app>
    <span>222</span>
  </my-app>
</body>

In summary: Is it possible and advisable to use Angular components throughout a non-Angular app? Is it possible to have 2 visible instances of the same Angular Module simultaneously?

Thanks!

3
  • Can you add some html that illustrates your problem? Shortly it's possible Commented Apr 11, 2017 at 21:21
  • @yurzui I just updated the OP with an HTML example. Let me know if it's still unclear. Commented Apr 11, 2017 at 21:41
  • can you give some examples of how you manage to add angular components to non angular applications? please Commented Jun 8, 2018 at 22:39

1 Answer 1

3

Following your scenario i would write the following code:

let bootstrapComponentFn: (node: HTMLElement) => void;

platformBrowserDynamic().bootstrapModule(AppModule).then((moduleRef: 

  NgModuleRef<AppModule) => {
    const appRef = moduleRef.injector.get(ApplicationRef);
    const zone: NgZone = moduleRef.injector.get(NgZone);
    const rootComponentFactory = (moduleRef as any).bootstrapFactories[0];  

    bootstrapComponentFn = (node) => {
      zone.run(() => {
        const compRef = rootComponentFactory.create(Injector.NULL, [], node);
       appRef.attachView(compRef.hostView);
      })
    }; 
  });
}

Some time later

setTimeout(function() {
  let node = document.createElement('my-app');
  document.body.appendChild(node);

  bootstrapComponentFn(node);
}, 2000);

See also Plunker Example

Sign up to request clarification or add additional context in comments.

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.