【问题标题】:angular 4+ assign @Input for ngComponentOutlet dynamically created componentangular 4+ 为 ngComponentOutlet 动态创建的组件分配 @Input
【发布时间】:2017-03-01 03:27:56
【问题描述】:

在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;
}

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

【问题讨论】:

  • 如何从模板向动态创建的组件发送信息?你使用@Input 装饰器还是其他东西?
  • 这取决于“来自模板”的信息、来源和含义。如果您需要支持,您需要提供更多详细信息。
  • @GünterZöchbauer 我已经更新了问题。如果您需要更多信息,请告诉我

标签: javascript angular typescript


【解决方案1】:

【讨论】:

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

在@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;
}

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

dynamicLoadedComponentA.ts

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

// data from parent
public Context: object;

// ...

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

dynamic.component.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));
    }
  }
}

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

app.html

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

app.ts

// ...
  private _settingsData: IDynamicComponent = {
    component: DynamicLoadedComponentA,
    context: { SomeValue: 42 },
    caller: this
  };
// ...

【讨论】:

  • 此解决方案是否适用于提前编译?
  • 目前,未使用 AOT 进行测试,但我会在不久的将来尝试对此进行测试并补充我的帖子。
  • 问题是针对 ngComponentOutlet 的。没有这个指令,代码会变得很乱。
【解决方案3】:

我认为你现在可以使用

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

专门为这个问题制作的

【讨论】:

    猜你喜欢
    • 2017-10-20
    • 2017-12-28
    • 2017-10-21
    • 1970-01-01
    • 2017-08-27
    • 1970-01-01
    • 2017-03-15
    • 1970-01-01
    • 2021-05-16
    相关资源
    最近更新 更多