угловой 5: взаимообмен местоположений динамических компонентов
Я хочу поменять местами динамически размещенные компоненты внутри представления.
т. е. я создал динамически компоненты с id = 1 и 2, как показано на рисунке.
Теперь мне нужно поменять позиции обоих компонентов, но как?
одно я знаю (только теоретически), что местоположение может быть изменено с помощью метода перемещения внутри ViewContainerRef class
через объект as viewContainerRef.move(componentRef.hostView, index)
.
I пробовал, но позиции не менялись.
@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);
Я прочитал документацию ViewContainerRef на угловой.Ио и прочитал почти тот же вопрос относительно этой проблемы, но не смог понять или решить эту проблему.
3 ответов
почему бы вам не привязать два динамических компонента к массиву? например, если у вас есть "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>
когда вам нужно поменять свои позиции, вам просто нужно манипулировать массивом, а angular заботится об остальном:
this.renderArray = this.renderArray.reverse();
он будет повторно отображать контейнеры ngFor в новом порядке. См.рабочий пример здесь.
решил эту проблему.
что я сделал?
Я изменил значения, вместо того, чтобы менять местами расположения компонентов
т. е. Я заменил значения
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 для перемещения представления в текущем контейнере.
основываясь на этой строке, я бы попытался ...
let ref = this.location.viewContainerRef;
ref.detach(ref.indexOf(componentRef.hostView));
ref.insert(componentRef.hostView, 0);
редактировать Я создал рабочий пример использование Angular в прямом эфире пример Динамический Загрузчик Компонентов.
вот код, относящийся к вопросу:
// 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
. Поменял detach
и insert
на move
и это работает. пример здесь. Соответствующий код:
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);