我想在视图中交换动态放置的组件的位置。
即我已经动态创建了id = 1和2的组件,如图所示。
现在我需要交换两个组件的位置但是如何?
我知道的一件事(只有理论上)是位置可以通过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文档并阅读了有关此问题的几乎相同的问题,但无法理解或解决此问题。
为什么不将两个动态组件绑定到数组?例如,如果您有“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 <=> 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,提出这个建议
我没有试过这个,但阅读文档听起来像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.
}
}
和move
为detach
,它的工作原理。 insert
在这里。相关代码:
move
现在我想知道你和Example争斗的问题是否是零指数。要使组件成为容器视图中的第一个组件,您需要为索引传递零。使它第二次通过一个,依此类推。所以你的代码会改变如下:
viewContainerRef.move(componentRef.hostView, 0);
// comment out the previous two lines to see that ads are inserted at the bottom.