Angular2:在DOM中将动态组件作为容器的子代插入 [英] Angular2: Insert a dynamic component as child of a container in the DOM

查看:82
本文介绍了Angular2:在DOM中将动态组件作为容器的子代插入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有一种方法可以动态地将组件作为Angular 2中DOM标签的(不是同级)插入?

Is there a way to insert dynamically a component as a child (not a sibling) of a DOM tag in Angular 2?

周围有很多示例可以插入动态组件作为给定<​​c0>标记的同级,例如(从RC3开始):

There are plenty of examples around there to insert a dynamic component as a sibling of a given ViewContainerRef's tag, like (as of RC3):

@Component({
  selector: '...',
  template: '<div #placeholder></div>'
})
export class SomeComponent {
  @ViewChild('placeholder', {read: ViewContainerRef}) placeholder;

  constructor(private componentResolver: ComponentResolver) {}

  ngAfterViewInit() {
    this.componentResolver.resolveComponent(MyDynamicComponent).then((factory) => {
        this.componentRef = this.placeholder.createComponent(factory);
    });
  }
}

但这会生成一个类似于以下内容的DOM:

But this generates a DOM similar to:

<div></div>
<my-dynamic-component></my-dynamic-component>

预期结果:

<div>
    <my-dynamic-component></my-dynamic-component>
</div>

使用SomeComponentViewContainerRef具有相同的结果,它仍将生成的组件作为同级而不是子级插入.对于模板为空并且将动态组件插入模板(在组件选择器标记内)的解决方案,我会没事的.

Using the SomeComponent's ViewContainerRef has the same result, it is still inserting the generated component as a sibling, not a child. I would be okay with a solution where the template is empty and dynamic components are inserted in the template (within the component selector tag).

使用ng2-dragula之类的库从动态组件列表中拖动时,DOM结构非常重要,并且从模型更新中受益.额外的div在可拖动元素的列表中,但在模型外部,这破坏了拖放操作.放下逻辑.

The DOM structure is very important when using libraries like ng2-dragula to drag from a list of dynamic components and benefit from the model updates. The extra div is in the list of draggable elements, but outside the model, breaking the drag & drop logic.

有人说这是不可能的(评论),但这听起来像是一个非常令人惊讶的限制.

Some say it is not possible (c.f. this comment), but it sounds like a very surprising limitation.

推荐答案

TL; DR :将<div #placeholder></div>替换为<div><ng-template #placeholder></ng-template></div>以插入div内.

TL;DR: replace <div #placeholder></div> with <div><ng-template #placeholder></ng-template></div> to insert inside the div.

这是一个有效的stackblitz示例 (角度6),以及相关代码:

Here is a working stackblitz example (Angular 6), and the relevant code:

@Component({
  selector: 'my-app',
  template: `<div><ng-template #container></ng-template></div>`
})
export class AppComponent implements OnInit {

    @ViewChild('container', {read: ViewContainerRef}) viewContainer: ViewContainerRef;

    constructor(private compiler: Compiler) {}

    ngOnInit() {
      this.createComponentFactory(MyDynamicComponent).then(
        (factory: ComponentFactory<MyDynamicComponent>) => this.viewContainer.createComponent(factory),
        (err: any) => console.error(err));
    }

    private createComponentFactory(/*...*/) {/*...*/}

}

<ng-container #placeholder></ng-container>似乎也可以正常工作(用ng-container替换ng-template).我喜欢这种方法,因为<ng-container>明确针对此用例(不添加标签的容器),并且可以在NgIf之类的其他情况下使用,而无需包装在真正的标签中.

It seems <ng-container #placeholder></ng-container> is also working (replace ng-template by ng-container). I like this approach because <ng-container> is clearly addressed to this usecase (a container that don't add a tag) and can be used in other situations like NgIf without wrapping in a real tag.

PS:@GünterZöchbauer在一条评论中将我引向正确的讨论,然后我终于回答了我自己的问题.

PS: @GünterZöchbauer directed me to the right discussion in a comment, and I finally answered my own question.

编辑[2018-05-30]:已更新为stackblitz链接,以提供最新的有效示例.

这篇关于Angular2:在DOM中将动态组件作为容器的子代插入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆