Using Angular 2 Components in the Entire Angular Application
I have a fork of an existing, mature, non-w500> web application. I also have some existing Angular 2 components from a separate application that I want to reuse. I would like to sprinkle existing Angular components into an Angular app in different places. I would like to know if this is possible and advisable. Note that this is similar but not identical to spray Angular 2 component on a non-Angular page . I have a more specific scenario that I describe below.
I have currently figured out how to add separate instances of these Angular components by loading the module that wraps my desired component. For example. if i want to inject AppComponent into my existing 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 just add the element my-app
and load the module like this:
platformBrowserDynamic().bootstrapModule(AppModule);
This works great and gives the exact results I want for a single AppComponent instance. However, my use cases require that I have two concurrent AppComponent instances in different places in the DOM. If I try to load the AppModule a second time, then the main Angular code attaches the second AppModule to the element my-app
that appears first in the DOM, effectively erasing my first AppModule instance. Is there a way to tell Angular which element to my-app
add to? Or is there some way to get around this?
Example HTML :
Let's say add <my-app>
to <body>
. Then my HTML looks like this:
<body>
<my-app>
</my-app>
</body>
Then if I call platformBrowserDynamic().bootstrapModule(AppModule);
and set value = '111'
anywhere on the AppComponent, my HTML looks like this:
<body>
<my-app>
<span>111</span>
</my-app>
</body>
Then I add another selector to the HTML my-app
, so it looks like this:
<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 this:
<body>
<my-app>
<span>222</span>
</my-app>
<my-app>
</my-app>
</body>
when i need the desired result:
<body>
<my-app>
<span>111</span>
</my-app>
<my-app>
<span>222</span>
</my-app>
</body>
In short: Is it possible and advisable to use Angular components throughout an Angular application? Is it possible to have 2 visible instances of the same Angular module at the same time?
Thank!
source to share
Following your scenario, I will 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 Plunger example
source to share