角度5:动态组件的交换位置

时间:2018-04-03 07:41:19

标签: angular typescript angular5

我想在视图中交换动态放置的组件的位置。

即。我已经动态创建了id = 1和2的组件,如图所示。

enter image description here

现在我需要交换两个组件的位置但是如何?

我知道的一件事(只有理论上)是位置可以通过ViewContainerRef class对象内的移动方法更改为viewContainerRef.move(componentRef.hostView, index)

我尝试了但是位置没有互换。

@ViewChild(ContainerRefDirective) location: ContainerRefDirective;

let componentFactory = this.factoryResolver.resolveComponentFactory(EntryComponent);
let componentRef = this.location.viewContainerRef.createComponent(componentFactory);

let entryComponent: EntryComponent = componentRef.instance;
// lets say counter is variable that increments its value on new component creation.
entryComponent.Id = ++counter; 

// move method is being called right after a new component is created and placed. 
//this piece of code is in the same method (that is creating the dynamic components)
this.location.viewContainerRef.move(componentRef.hostView, 1);

我已阅读angular.io上的ViewContainerRef文档,并阅读了有关此问题的几乎相同的问题,但无法理解或解决此问题。

3 个答案:

答案 0 :(得分:11)

为什么不将两个动态组件绑定到数组? 例如,如果您有“objectA”和“objectB”:

this.renderArray.push(objectA);
..
this.renderArray.push(objectB);

你的html看起来像这样:

<ng-container *ngFor="let renderObject of renderArray">
   <<you can reference objectA and objectB by using "renderObject.value" etc.>>
</ng-container>

当你需要交换他们的位置时,你只需要操纵数组,而角度就会照顾其余的:

this.renderArray = this.renderArray.reverse();

它将以新的顺序重新呈现ngFor容器。 请参阅working example here

答案 1 :(得分:6)

解决了这个问题。

我做了什么?

  

我更改了值,而不是交换组件&#39;地点

     

即。我替换了值1 <=> 2,看起来组件是互换的。

如何?

// array to hold the newly created component instances
entryComponents: EntryComponent[] = new Array<EntryComponent>();

然后将新创建的组件推入该数组

let factoryResolver = this.factoryResolver.resolveComponentFactory(EntryComponent);    
let componentRef = this.location.viewContainerRef.createComponent(factoryResolver);

this.entryComponents.push(componentRef.instance); // getting components' instances

现在交换值,使组件看起来像互换。

感谢 @ForestG ,了解此建议

答案 2 :(得分:1)

我还没试过这个,但是阅读文档听起来像move并不是正确的方法。听起来像移动是为了#34;添加&#34;视图的现有组件。

来自detach的文档:

  

与insert一起使用以在当前容器中移动View。

基于这一行,我试试......

let ref = this.location.viewContainerRef;
ref.detach(ref.indexOf(componentRef.hostView));
ref.insert(componentRef.hostView, 0);

修改 我使用Angular的example实时示例创建了一个有效的Dynamic Component Loader

以下是与问题相关的代码:

// ShaneCoder - don't clear so we get multiple ads to demonstrate move.
// viewContainerRef.clear();

// ShaneCoder - only create 4 ads
if (viewContainerRef.length<4) {

    let componentRef = viewContainerRef.createComponent(componentFactory);
    (<AdComponent>componentRef.instance).data = adItem.data;

    // ShaneCoder ad is inserted at the bottom (no index parameter).  Move it up if there are multiple ads.
    if (viewContainerRef.length>=1) {
        // we're not the first ad
        // move new ad to top using detach and insert (the next two lines answer the original question) 
        viewContainerRef.detach(viewContainerRef.indexOf(componentRef.hostView));
        viewContainerRef.insert(componentRef.hostView, 0);
        // comment out the previous two lines to see that ads are inserted at the bottom.
    }
}

修改2

在发布最后一次修改后,我没有尝试move。将detachinsert切换为move,然后就可以了。 Example在这里。相关代码:

viewContainerRef.move(componentRef.hostView, 0);
// comment out the previous two lines to see that ads are inserted at the bottom.

现在我想知道你与move打架的问题是否是零指数。要使组件成为容器视图中的第一个组件,您需要为索引传递零。使它第二次通过一个,依此类推。所以你的代码会改变如下:

this.location.viewContainerRef.move(componentRef.hostView, 0);