Angular7 cdkDropList between arrays with dynamic lists

Viewed 5241

I get the following error: ERROR TypeError: Cannot assign to read only property '2' of string 'One' from the following datalist that I created to mimic the form that my actual data looks like, and the template view that I have seen to use from angular material documentation for dynamic lists like these. But even though they say what to do, they do not give an example..

I can not get the following to work:

Component:

lists = [];

ngOnInit() {
    this.lists = [{number: 'One', amount: [1, 2, 3, 4]}, {number: 'Two', amount: [5, 6, 7, 8]}, {number: 'Three', amount: [9, 10, 11, 12]}];
}

drop(event: CdkDragDrop<string[]>) {
    if (event.previousContainer === event.container) {
        moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
    } else {
        transferArrayItem(event.previousContainer.data,
            event.container.data,
            event.previousIndex,
            event.currentIndex);
    }
}

Template:

<div cdkDropList [cdkDropListData]="list.number" *ngFor="let list of lists" (cdkDropListDropped)="drop($event)">
    {{list.number}}
    <div cdkDrag [cdkDragData]="item" *ngFor="let item of list.amount">
        {{item}}
    </div>
</div>
2 Answers

You should get the actual index of your list item.. Try this:

TS:

activeNumIndex: number;
enter(i) {
    this.activeNumIndex = i;
  }

  drop(event: CdkDragDrop<string[]>) {
    if (event.previousContainer === event.container) {
      moveItemInArray(this.lists[this.activeNumIndex].amount, event.previousIndex, event.currentIndex);
    } else {
      transferArrayItem(event.previousContainer.data,
        event.container.data,
        event.previousIndex,
        event.currentIndex);
    }
  }

HTML:

<div cdkDropList [cdkDropListData]="list.number" *ngFor="let list of lists; let i=index;" (cdkDropListDropped)="drop($event)">
    {{list.number}}
    <div cdkDrag [cdkDragData]="item" *ngFor="let item of list.amount" (mouseenter)="enter(i)" style="border:1px solid black">
        {{item}}
    </div>
</div>

Here's a duplicate in Stackblitz

if you want to move item between arrays, you can mark each cdkDropList using #mark-name and use cdkDropListConnectedTo directive to connect them.

And if the number of cdkDropList is not known, you can use cdkDropListGroup directive to setup connection between the cdkDropList automatically.

the example would be:

<div cdkDropListGroup>
    <div cdkDropList *ngFor="let list of lists; let i=index;"
         [cdkDropListData]="list.number" 
         (cdkDropListDropped)="drop($event)">{{list.number}}

           <div cdkDrag *ngFor="let item of list.amount"
                [cdkDragData]="item"  
                (mouseenter)="enter(i)" 
                style="border:1px solid black">{{item}}
           </div>
    </div>
</div>

Stackblitz Example

here is some example code copied from angular material example

and with dynamic number of list

hope it helps, cheers!

Related