Drag and Drop: After dropping a container to another cdkDropList inside of a cdkDropListGroup previousContainer is not updated

What are you trying to do?
I try to move a dynamically inserted component from one cdkDropList to another inside of a cdkDropListGroup.

Here an excerpt of the HTML:

<div class="container-fluid mt-3">
    <div class="row" cdkDropListGroup>
        <div class="col-4 border min-vh-100" #dropList0Ref
             cdkDropList
             [cdkDropListData]="columns[0]"
             (cdkDropListDropped)="onDrop($event)">
            <ng-container #componentContainer0></ng-container>
        </div>
        <div class="col-4 border min-vh-100" #dropList1Ref
             cdkDropList
             [cdkDropListData]="columns[1]"
             (cdkDropListDropped)="onDrop($event)">
            <ng-container #componentContainer1></ng-container>
        </div>
        <div class="col-4 border min-vh-100" #dropList2Ref
             cdkDropList
             [cdkDropListConnectedTo]="['dropList0Ref', 'dropList1Ref']"
             [cdkDropListData]="columns[2]"
             (cdkDropListDropped)="onDrop($event)">
            <ng-container #componentContainer2></ng-container>
        </div>
    </div>
</div>

excerpt of component.ts

    ...
    columns: any[] = [ [], [], [] ];
    components0: ComponentRef<any>[] = [];
    components1: ComponentRef<any>[] = [];
    components2: ComponentRef<any>[] = [];
    
    @ViewChild('componentContainer0', { static: true, read: ViewContainerRef })
    componentContainer0: ViewContainerRef;

    @ViewChild('componentContainer1', { static: true, read: ViewContainerRef })
    componentContainer1: ViewContainerRef;

    @ViewChild('componentContainer2', { static: true, read: ViewContainerRef })
    componentContainer2: ViewContainerRef;

    
    ngAfterViewInit () {
        this.add(LogBookComponent, 0);
        this.add(CustomerListComponent, 0);
    }
    
    add (component, columnIndex: number) {
        let componentFactory;
        let cmp: ComponentRef<any>;
        let id;

        switch (columnIndex) {
            case 0:
                componentFactory = this.resolver.resolveComponentFactory(component);
                cmp = this.componentContainer0.createComponent(componentFactory);

                this.components0.push(cmp);
                id = cmp.componentType.name;
                this.columns[ 0 ].push({ id, title: `Gadget ${ id }` });
                cmp.changeDetectorRef.detectChanges();
                break;
            case 1:
                componentFactory = this.resolver.resolveComponentFactory(component);
                cmp = this.componentContainer1.createComponent(componentFactory);
                id = cmp.componentType.name;

                this.components1.push(cmp);
                this.columns[ 1 ].push({ id, title: `Gadget ${ id }` });
                cmp.changeDetectorRef.detectChanges();
                break;
            case 2:
                componentFactory = this.resolver.resolveComponentFactory(component);
                cmp = this.componentContainer2.createComponent(componentFactory);
                id = cmp.componentType.name;

                this.components2.push(cmp);
                this.columns[ 2 ].push({ id, title: `Gadget ${ id }` });
                cmp.changeDetectorRef.detectChanges();
                break;

            default:
                throw new Error('only three columns are supported');
        }
    }

    onDrop (event: CdkDragDrop<{}[]>) {
        console.log(``);
        console.log(``);
        console.log(``);
        console.log('event', event);
        console.log('this.columns', this.columns);

        const previousContainerId = this.getIdOf(event.previousContainer.id);
        const currentContainerId = this.getIdOf(event.container.id);

        console.log('previousContainerId', previousContainerId);
        console.log('currentContainerId', currentContainerId);

        if (event.previousContainer == event.container) {
            console.log(`moving inside ${ event.previousIndex } -> ${ event.currentIndex }`);

            switch (currentContainerId) {
                case 0:
                    this.componentContainer0.move(this.components0[ event.previousIndex ].hostView, event.currentIndex);
                    moveItemInArray(this.components0, event.previousIndex, event.currentIndex);
                    break;
                case 1:
                    this.componentContainer1.move(this.components1[ event.previousIndex ].hostView, event.currentIndex);
                    moveItemInArray(this.components1, event.previousIndex, event.currentIndex);
                    break;
                case 2:
                    this.componentContainer2.move(this.components2[ event.previousIndex ].hostView, event.currentIndex);
                    moveItemInArray(this.components2, event.previousIndex, event.currentIndex);
                    break;
            }
        }
        else {
            console.log(`transferring ${ previousContainerId } -> ${ currentContainerId } (${ event.previousIndex } -> ${ event.currentIndex })`);
            let previousComponents;
            let currentComponents;

            transferArrayItem(previousComponents, currentComponents, event.previousIndex, event.currentIndex);
            transferArrayItem(this.columns[ previousContainerId ], this.columns[ currentContainerId ], event.previousIndex, event.currentIndex);

            switch (currentContainerId) {
                case 0:
                    currentComponents = this.components0;
                    switch (previousContainerId) {
                        case 0:
                            // not possible is an move in array
                            console.log(`not possible is an move in array`);
                            break;
                        case 1:
                            previousComponents = this.components1;
                            this.componentContainer0.move(this.components1[ event.previousIndex ].hostView, event.currentIndex);
                            break;
                        case 2:
                            previousComponents = this.components2;
                            this.componentContainer0.move(this.components2[ event.previousIndex ].hostView, event.currentIndex);
                            break;
                    }
                    break;
                case 1:
                    currentComponents = this.components1;
                    switch (previousContainerId) {
                        case 0:
                            previousComponents = this.components0;
                            this.componentContainer1.move(this.components0[ event.previousIndex ].hostView, event.currentIndex);
                            break;
                        case 1:
                            // not possible is an move in array
                            console.log(`not possible is an move in array`);
                            break;
                        case 2:
                            previousComponents = this.components2;
                            this.componentContainer1.move(this.components2[ event.previousIndex ].hostView, event.currentIndex);
                            break;
                    }
                    break;
                case 2:
                    currentComponents = this.components2;
                    switch (previousContainerId) {
                        case 0:
                            previousComponents = this.components0;
                            this.componentContainer2.move(this.components0[ event.previousIndex ].hostView, event.currentIndex);
                            break;
                        case 1:
                            previousComponents = this.components1;
                            this.componentContainer2.move(this.components1[ event.previousIndex ].hostView, event.currentIndex);
                            break;
                        case 2:
                            // not possible is an move in array
                            console.log(`not possible is an move in array`);
                            break;
                    }
                    break;
            }
        }
    }
...

Reproduction
I’m able to move both components inside one cdkDropList. I also can move from on to another cdkDropList. But if I try to move it back to first cdkDropList or move it inside the new cdkDropList, an error occurs. If I debug the $event the event.previousContainer.id is still 0. So something wasn’t updated. But I don’t know what.

I know there are way’s to write it shorter but before starting refactoring I need a working drag and drop.

StackBlitz: https://stackblitz.com/edit/angular-ivy-iuwvmb?file=src%2Fapp%2Fapp.component.ts

Steps to reproduce in Stackblitz:

  1. Move Hello Component 1 to second column
  2. Try to move Hello Component 1 back to first column
  3. see debug information and error in console

Environment

  • Angular: 9.1.9
  • CDK/Material: 9.2.4
  • Browser(s): Chrome
  • Operating System (e.g. Windows, macOS, Ubuntu): macOS

Source: Angular Questions