angular 4+ 为 ngComponentOutlet 动态创建的组件分配 @Input

IT技术 javascript angular typescript
2021-03-21 02:06:22

在 Angular 4 中动态创建一个组件,你可以使用ngComponentOutlet指令:https : //angular.io/docs/ts/latest/api/common/index/NgComponentOutlet-directive.html

像这样:

动态组件

@Component({
  selector: 'dynamic-component',
  template: `
     Dynamic component
  `
})
export class DynamicComponent {
  @Input() info: any;
}

应用程序

@Component({
  selector: 'my-app',
  template: `
     App<br>
     <ng-container *ngComponentOutlet="component"></ng-container>
  `
})
export class AppComponent {
  this.component=DynamicComponent;
}

如何@Input() info: any;在此模板中传递信息<ng-container *ngComponentOutlet="component"></ng-container>

3个回答
@GünterZöchbauer 谢谢!我会尝试ngComponentOutletContainer+providers选项。我也会检查感谢链接。我的替代方案是更新双方模型的服务,但我真的更愿意将其作为最后的选择。
2021-04-29 02:06:22
谢谢。到 v4.0 发布时,是否有可能拥有不同的 ngComponentOutlet?我的意思是有一些选项可以解决这个问题?
2021-05-03 02:06:22
@GünterZöchbauer 所以,如果我动态调用一个组件,ngComponentOutlet唯一的方法是通过创建自定义指令或使用某种服务来将modeldata从我当前的模板/组件发送到动态组件?ngComponentOutlet没有任何内置功能来传达两个组件:调用者和被调用者?甚至没有ngComponentOutletInjector
2021-05-06 02:06:22
我不知道这些计划。结论是,支持输入对于第一个版本来说太复杂了,他们想按原样发布,然后最终再次解决这个问题,但从那以后我就没有看到相关的讨论(这没有多大意义,因为我没有没有太多时间检查)
2021-05-09 02:06:22
ngComponentOutletInjector只是通过一个定制的注射器。如果您将提供程序添加到您使用的组件中,ngComponentOutletContainer对于大多数用例,您将自动获得相同的结果。我认为他们计划支持在 Angular4 中传递一些上下文。不确定这是否已经降落。
2021-05-09 02:06:22

在@Günter Zöchbauer 的帖子的帮助下,我以这种方式解决了一个类似的问题——我希望你能以某种方式适应它。

首先我定义了一些接口:

// all dynamically loaded components should implement this guy
export interface IDynamicComponent { Context: object; }

// data from parent to dynLoadedComponent
export interface IDynamicComponentData {
  component: any;
  context?: object;
  caller?: any;
}

然后我在动态加载的组件中实现了它们

动态加载组件A.ts

// ...
export class DynamicLoadedComponentA implements IDynamicComponent {
// ...

// data from parent
public Context: object;

// ...

之后,我构建了一个负责魔法的新组件。这里重要的是我必须注册所有 dyn。加载组件作为 entryComponents。

动态组件.ts

@Component({
  selector: 'ngc-dynamic-component',
  template: ´<ng-template #dynamicContainer></ng-template>´,
  entryComponents: [ DynamicLoadedComponentA ]
})
export class DynamicComponent implements OnInit, OnDestroy, OnChanges {
  @ViewChild('dynamicContainer', { read: ViewContainerRef }) public dynamicContainer: ViewContainerRef;

  @Input() public componentData: IDynamicComponentData;

  private componentRef: ComponentRef<any>;
  private componentInstance: IDynamicComponent;

  constructor(private resolver: ComponentFactoryResolver) { }

  public ngOnInit() {
    this.createComponent();
  }

  public ngOnChanges(changes: SimpleChanges) {
    if (changes['componentData']) {
      this.createComponent();
    }
  }

  public ngOnDestroy() {
    if (this.componentInstance) {
      this.componentInstance = null;
    }
    if (this.componentRef) {
      this.componentRef.destroy();
    }
  }

  private createComponent() {
    this.dynamicContainer.clear();
    if (this.componentData && this.componentData.component) {
      const factory: ComponentFactory<any> = this.resolver.resolveComponentFactory(this.componentData.component);
      this.componentRef = this.dynamicContainer.createComponent(factory);
      this.componentInstance = this.componentRef.instance as IDynamicComponent;

      // fill context data
      Object.assign(this.componentInstance.Context, this.componentData.context || {});

      // register output events
      // this.componentRef.instance.outputTrigger.subscribe(event => console.log(event));
    }
  }
}

这里是这个闪亮的新东西的用法:

应用程序.html

<!-- [...] -->
<div>
  <ngc-dynamic-component [componentData]="_settingsData"></ngc-dynamic-component>
</div>
<!-- [...] -->

应用程序

// ...
  private _settingsData: IDynamicComponent = {
    component: DynamicLoadedComponentA,
    context: { SomeValue: 42 },
    caller: this
  };
// ...
不过问题是针对 ngComponentOutlet 的。如果没有这个指令,代码就会变得很乱。
2021-05-07 02:06:22
目前,尚未使用 AOT 进行测试,但我会在不久的将来尝试对此进行测试并补充我的帖子。
2021-05-09 02:06:22
此解决方案是否适用于提前编译?
2021-05-12 02:06:22

我想现在你可以使用

https://www.npmjs.com/package/ng-dynamic-component

专门针对这个问题制作的