I have been scrapping together as much as I could trying to get this to work from everywhere on the internet but I have reached a point where I just don't know how to proceed. I am using Angular 18 and CDK Drag and Drop. I am trying to have a list of nested items where there are two different types of items, those who can have children, and those who can't. The nesting is infinite, so you can technically have an endless amount of items who can have children inside each other. I finally managed to get the basics of it to work, however now I have an issue with its responsiveness. In order to re-organize an item inside a container, I need to first move it to another container. I think it is something related to what the item is connected to but at this point I am out of ideas. Please check out the following code and a video to clarify what I mean exactly. HTML (root-container): <div cdkDropList [id]="root.uId" [cdkDropListData]="root.children" [cdkDropListConnectedTo]="connectedTo" (cdkDropListDropped)="onDragDrop($event)"> <ng-container *ngFor="let item of root.children; trackBy: trackById; let i = index"> <list-item [item]="item" [parent]="root" [index]="i" [connectedTo]="connectedTo" (itemDrop)="onDragDrop($event)"> </list-item> </ng-container> </div> TS (from root): onDragDrop = (event: CdkDragDrop<Array<Item>>) => { if (event.previousContainer === event.container) { this.store.updatingForm = true; moveItemInArray( event.container.data, event.previousIndex, event.currentIndex ); } else { if(this.store.findItemById(this.root, event.container.id).isContainer) { this.store.updatingForm = true; transferArrayItem( event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex ); } } this.store.changedRoot = this.root; }; private getIdsRecursive(item: Item): string[] { let ids = [item.uId]; item.children.forEach(childItem => { ids = ids.concat(this.getIdsRecursive(childItem)); }); return ids; } HTML (list-item): <ng-container *ngIf="item"> @if (!item.isContainer) { <div [class]="item.isContainer ? 'fieldset item' : 'item'" cdkDrag [id]="item.uId"> <div style="display: flex; flex-direction: row" class="item-content"> <p class="name">{{ item.name }}</p> <p class="label">{{ item.label }}</p> <p class="class">{{ item._class }}</p> <p class="description">{{ item.description ? item.description : "" }}</p> <div id="constraints" class="constraints"> @if (isFieldHaveConstraint()) { @for (constraint of item.constraints; track constraint) { <span (click)="openFieldConstraintPage(item)" matTooltip="{{getConstraintText(constraint['_class'])}}" class="mr-2 btn-pointer"> {{ getConstraintText(constraint['_class']) }}</span> } } @else { <strong> <button mat-button class="icon-button" (click)="openFieldConstraintPage(item)"> <fa-icon [icon]="faPlus"></fa-icon> </button> </strong> } <ng-template #constraints> @for (constraint of item.constraints; track constraint) { <span (click)="openFieldConstraintPage(item)" matTooltip="{{getConstraintText(constraint['_class'])}}" class="mr-2 btn-pointer">{{ getConstraintText(constraint['_class']) }}</span> } </ng-template> </div> <div class="action-btns"> <button class="menu-btn" mat-icon-button (click)="openUpdateField(item)"> <fa-icon [icon]="faPenToSquare"></fa-icon> </button> <button class="menu-btn" mat-icon-button (click)="openDeleteConfirmationDialog(item)"> <fa-icon [icon]="faDeleteLeft"></fa-icon> </button> </div> </div> </div> } @else { <div [class]="item.isContainer ? 'fieldset item' : 'item'" cdkDrag cdkDropList cdkDropListGroup [id]="item.uId" [cdkDropListData]="item.children" [cdkDropListConnectedTo]="connectedTo" (cdkDropListDropped)="onDragDrop($event)" [cdkDropListDisabled]="!item.isContainer"> <div style="display: flex; flex-direction: row" class="item-content fieldset" style="display: flex; align-items: center; justify-content: space-between"> <p>{{ item.name }}</p> <div class="action-btns"> <button class="menu-btn" mat-icon-button (click)="openUpdateField(item)"> <fa-icon [icon]="faPenToSquare"></fa-icon> </button> <button class="menu-btn" mat-icon-button (click)="openDeleteConfirmationDialog(item)"> <fa-icon [icon]="faDeleteLeft"></fa-icon> </button> </div> </div> <ng-container *ngFor="let nextItem of item.children; let i = index"> <div back class="sub-item"> <list-item [item]="nextItem" [parent]="item" [index]="i" [connectedTo]="connectedTo" (itemDrop)="onDragDrop($event)"> </list-item> </div> </ng-container> </div> } </ng-container> TS (from list-item): public onDragDrop(event: CdkDragDrop<Array<Item>>): void { this.itemDrop.emit(event); } Continue reading...