угловой 5: взаимообмен местоположений динамических компонентов

Я хочу поменять местами динамически размещенные компоненты внутри представления.

т. е. я создал динамически компоненты с id = 1 и 2, как показано на рисунке.

enter image description here

Теперь мне нужно поменять позиции обоих компонентов, но как?

одно я знаю (только теоретически), что местоположение может быть изменено с помощью метода перемещения внутри 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);