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

问题描述 投票:12回答:3

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

即我已经动态创建了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文档并阅读了有关此问题的几乎相同的问题,但无法理解或解决此问题。

angular typescript angular5
3个回答
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


6
投票

解决了这个问题。

What I did?

我更改了值,而不是交换组件的位置

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

How?

// 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,提出这个建议


1
投票

我没有试过这个,但阅读文档听起来像move不是正确的方法。听起来像move是将现有组件“添加”到视图中。

来自detach的文档:

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

基于那条线,我试试......

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

编辑我使用Angular live example为qazxsw poi创建了一个有效的qazxsw poi。

这是与问题相关的代码:

example

编辑2

在发布最后一次编辑后意识到我没有尝试过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. } } movedetach,它的工作原理。 insert在这里。相关代码:

move

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

viewContainerRef.move(componentRef.hostView, 0);
// comment out the previous two lines to see that ads are inserted at the bottom.
© www.soinside.com 2019 - 2024. All rights reserved.