Angular 7 - добавление поведения перетаскивания в динамически создаваемые компоненты - PullRequest
0 голосов
/ 13 мая 2019

Это продолжение предыдущего вопроса, который я задал для SO: Добавить директивы в селектор компонентов, когда он объявлен - Угловой 7

Я динамически создаю компоненты одним нажатием кнопки.Компоненты отображаются один под другим в виде списка.Я хочу представить поведение перетаскивания, чтобы пользователь мог переставлять компоненты после их создания.

В предыдущем вопросе я пытался использовать Angular-Material, но понял, что его нельзя использовать для компонентов, из-за проблемы добавления директивы "cdkDrag" к тегу селектора компонента и того факта, что cdkDropList и cdkDrag, возможно, должны быть в одном шаблоне.

У меня есть div как таковой в шаблоне:

<div cdkDropList style="margin: 20px" (cdkDropListDropped)="drop($event)">
    <div #container></div>
</div>

И я создаю пользовательские компоненты следующим образом:

@ViewChild('container', {read: ViewContainerRef})
  container: ViewContainerRef;

const childComponent = this.componentFactoryResolver.resolveComponentFactory(CustomComponent);
const component = this.container.createComponent(childComponent);

Это прекрасно работает.Можно ли вообще создавать перетаскиваемые динамически созданные компоненты?

Спасибо.

Ответы [ 2 ]

1 голос
/ 13 мая 2019

Наконец получил его на работу, благодаря ответу от MauriceNino.Я собираюсь отметить ответ Мориса как принятый, поскольку их решение отлично работает для одного компонента.

Получая решение Мориса для работы с несколькими компонентами, я натолкнулся на эту волшебную концепцию, называемую ng-container!Что за спасатель жизни!Мое решение заключается в следующем:

components=[];

const childComponent = this.componentFactoryResolver.resolveComponentFactory(CustomComponent);
this.components.push(childComponent);


drop(event: CdkDragDrop<CmpComponent[]>) {
  moveItemInArray(this.components, event.previousIndex, event.currentIndex);
}

Теперь для шаблона:

<div cdkDropList class="example-list" style="margin: 20px" (cdkDropListDropped)="drop($event)">
    <ng-container *ngFor="let cmp of components">
        <ng-container *ngIf="cmp.componentType.name=='Component1'">
            <app-Component1 cdkDrag></app-Component1>
        </ng-container>
        <ng-container *ngIf="cmp.componentType.name=='Component2'">
            <app-Component2 cdkDrag></app-Component2>
        </ng-container>
        <ng-container *ngIf="cmp.componentType.name=='Component3'">
            <app-Component3 cdkDrag></app-Component3>
        </ng-container>

    </ng-container>
</div>

Наконец, после недели поиска, он наконец-то работает!Спасибо!

0 голосов
/ 13 мая 2019

Обновление

Хотя это нормально работает с компонентами одного типа, если вам нужно использовать разные динамические типы компонентов, прочитайте комментарий Чайтаньи Бангеры ниже!

Оригинальный комментарий

Должно работать с чем-то вроде этого (CmpComponent будет вашим компонентом, который вы хотите вставить):

  components: CmpComponent[];

const childComponent = this.componentFactoryResolver.resolveComponentFactory(CustomComponent);
this.components.push(childComponent);


drop(event: CdkDragDrop<CmpComponent[]>) {
  moveItemInArray(this.components, event.previousIndex, event.currentIndex);
}
<div cdkDropList style="margin: 20px" (cdkDropListDropped)="drop($event)">
    <div cdkDrag *ngFor="let cmp of components">
        <app-cmp></app-cmp>
    </div>
</div>
...