angular - 在同一页面上多次引导 Angular 应用程序

标签 angular

我想在同一页面上多次引导 Angular 4 微型应用程序。基本上,对于类“.angular-micro-app”的每个实例,引导一个新的应用程序实例。

我知道传统上这些是单个父应用程序中的 Angular 组件。就我而言,这是不可能的,我需要同一页面上同一根级别应用程序(组件)的多个实例。这对于 AngularJS 1.x 来说是相当微不足道的,但对于 Angular 来说却令人沮丧。

例子:

index.html 片段:

<body>
<div class=“.angular-micro-app”></div>
…
<div class=“.angular-micro-app”></div> <!-- this element is NOT bootstrapping -->
</body>

应用程序组件.ts:

import { Component } from '@angular/core';

@Component({
  selector: '.angular-micro-app',
  template: require('./app.component.html'),
})
export class AppComponent { }

应用程序模块.ts:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
  ],
  providers: [

  ],
  bootstrap: [AppComponent],
})
export class AppModule { }

在主文件中,我正在进行基本的平台引导:

platformBrowserDynamic().bootstrapModule(AppModule);

最佳答案

这可以通过在 NgModule ngDoBootstrap 方法中手动引导根级组件来完成。

(请注意,在 Angular 5+ 中可能不再需要此方法,请参阅 this Angular PR)

我们首先找到我们想要引导的所有根元素并给它们一个唯一的 ID。然后对于每个实例,使用新 ID 破解码件工厂选择器并触发 Bootstrap 。

const entryComponents = [
  RootComponent,
];

@NgModule({
  entryComponents,
  imports: [
    BrowserModule,
  ],
  declarations: [
    RootComponent,
  ],
})
export class MyModule {
  constructor(private resolver: ComponentFactoryResolver) {}

  ngDoBootstrap(appRef: ApplicationRef) {
    entryComponents.forEach((component: any) => {
      const factory = this.resolver.resolveComponentFactory(component);
      let selectorName;
      let elements;

      // if selector is a class
      if (factory.selector.startsWith('.')) {
        selectorName = factory.selector.replace(/^\./, '');
        elements = document.getElementsByClassName(selectorName);

      // else assume selector is an element
      } else {
        selectorName = factory.selector;
        elements = document.getElementsByTagName(selectorName);
      }

      // no elements found, early return
      if (elements.length === 0) {
        return;
      }

      // more than one root level componenet found, bootstrap unique instances
      if (elements.length > 1) {
        const originalSelector = factory.selector;

        for (let i = 0; i < elements.length; i += 1) {
          elements[i].id = selectorName + '_' + i;
          (<any>factory).factory.selector = '#' + elements[i].id;
          appRef.bootstrap(factory);
        }

        (<any>factory).factory.selector = originalSelector;

      // only a single root level component found, bootstrap as usual
      } else {
        appRef.bootstrap(factory);
      }
    });
  }
}

现在,假设我们的 RootComponent 的选择器是 '.angular-micro-app' 这将按预期工作:

<body>
    <div class="angular-micro-app"></div>
    ...
    <div class="angular-micro-app"></div>
</body>

关于angular - 在同一页面上多次引导 Angular 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47020215/

相关文章:

c# - 将值从 Angular 服务应用程序发送到 C# 后端 Controller

javascript - 如何在创建 Observer 时强制评估 Observer 中的表达式,而不是在发出值时

angular - 如何使用 TypeScript 将多个参数传递给 Angular 中的 @Directives (@Components)?

Angular 2 : trying to load a component dynamically, 获取:类型错误:无法读取属性 'parentInjector'

angular - 尝试使用已损坏的 View : detectChanges event though the view is detached

javascript - ionic 2 存储不适用于变量

javascript - 如何以 Angular 查找给定数组列表的所有行中是否存在相同的值

angular - RouterLink 无法在子组件中工作

javascript - 如何显示Angular2的树形结构

node.js - Auth0 与 Angular2 "Supplied parameters do not match any signature of call target."