【问题标题】:Move angular component from one container to another将角度组件从一个容器移动到另一个容器
【发布时间】:2018-02-11 11:37:59
【问题描述】:

我正在构建一个具有多个值的组件,但不是复制值本身,而是复制整个输入组件:

<ng-content>
  <!-- here will be an input component of any type -->
</ng-content>

<button (click)="add()">Add</button>

<div #Container>
</div>

我参考@ContentChild@ViewChild('Container') - 这没什么大不了的。但是,我找不到通过单击“添加”按钮将由 ContentChild 表示的输入组件移动到由 ViewChild 表示的容器的平滑方法。

这是我现在拥有的解决方法。我通过ElementRef 引用它们,然后向下移动到纯DOM 操作:

const elContainer: HTMLElement = this._container.nativeElement;
elContainer.appendChild(this._input.nativeElement);

不知道有没有更好的办法。

更新:

@Sreekumar 建议使用 CDK 门户,其目的看起来很常见,但它的开销令人难以置信,看看(来自示例),它再次使用 DOM:

constructor(
 private componentFactoryResolver: ComponentFactoryResolver,
 private injector: Injector,
 private appRef: ApplicationRef,
) { } 

ngOnInit() {

    // Create a portalHost from a DOM element
    this.portalHost = new DomPortalHost(
      document.querySelector('#pageHeader'),
      this.componentFactoryResolver,
      this.appRef,
      this.injector
    );

    // Locate the component factory for the HeaderComponent
    this.portal = new ComponentPortal(HeaderComponent);

    // Attach portal to host
    this.portalHost.attach(this.portal);
}

【问题讨论】:

  • @Sreekumar,这看起来像是 Material 的一部分,有什么与主题无关的方式吗?
  • @Vladimir 这不是 Material 的一部分。这是一个由 Material 团队维护的通用库。
  • 是的,在深入学习之后感谢您,这确实是一个好方法。然而,这只与我对一个相当大的 UI 库的需求有关,如果我要运行一个小项目,我认为添加这个库会太多,所以我希望 @angular/core 有办法做到这一点。跨度>

标签: angular


【解决方案1】:

这是我不使用 DOM 的解决方案。

该示例创建多个动态组件并将它们从一个容器移动到另一个容器。

这是我们应该做的:

  1. 容器A类型为ViewContainerRef

  2. Container B 类型为ViewContainerRef

  3. 组件类型的ComponentRef; 我发现这非常重要,因为像 insert 这样的 ViewContainerRef 方法使用 ViewRef 您无法从任何其他参考中获得。键入,因此您无法使用 @ViewChild@ContentChild 然后移动它。所以这里的规则是:你要移动的组件应该是动态创建的,因为只有这样你才能得到 ComonentRef!你也可以在这里找到一些解释https://stackoverflow.com/a/45339558/3925894

以下是步骤:

变量。

private _componentFactory: ComponentFactory<SomeComponent>;

private _componentRef: ComponentRef<SomeComponent>;

@ViewChild('InputContainer', {read: ViewContainerRef})
private _inputContainer: ViewContainerRef;

@ViewChild('ItemsContainer', {read: ViewContainerRef})
private _itemsContainer: ViewContainerRef;

初始化。

public ngAfterViewInit(): void {

  this._componentFactory =
    this._componentFactoryResolver.resolveComponentFactory(SomeComponent);

  this._componentRef =
    this._inputContainer.createComponent(this._componentFactory);

  this._componentRef.changeDetectorRef.detectChanges();

}

动态创建和移动组件

private _add() {

  const index = this._inputContainer.indexOf(this._componentRef.hostView);

  this._inputContainer.detach(index);

  this._itemsContainer.insert(this._componentRef.hostView);

  this._componentRef =
    this._inputContainer.createComponent(this._componentFactory);

  this._componentRef.changeDetectorRef.detectChanges();

}

见 plunkr http://plnkr.co/edit/2eHE2S8hTKcQ8i7TidBF?p=preview

这对我有用。如您所见,没有 DOM。

【讨论】:

    猜你喜欢
    • 2016-11-29
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    • 1970-01-01
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多