3
votes

I am trying to filter a list of items using the Drag Material CDK... all is working well when my list is not filtered, however when I filter it, and drag and drop, I get the wrong item (wrong index) on the drop, I created a working example, as you can see, filter by let's say "av" and drag avocado to drop area and you will get Carrot as the index is referring to the old data source, any ideas are appreciated,

here is a working example of the problem: https://stackblitz.com/edit/angular-agf3kv-wjxwdm?file=app/cdk-drag-drop-disabled-sorting-example.css

Sean

4

4 Answers

2
votes

You should use itemsFiltered as cdkDopListData.

<div
  cdkDropList
  [cdkDropListData]="itemsFiltered" <-- HERE
  class="example-list"
  cdkDropListSortingDisabled
  (cdkDropListDropped)="drop($event)">
  <div class="example-box" *ngFor="let item of itemsFiltered" cdkDrag>{{item}}</div>
</div>

Stackblitz

2
votes

I had the same issue and having a getter function to get itemsFiltered bugged on my end for the data. Note that I'm working with dynamic lists, so the user can choose how many drag & drop lists are available and which.

I solved my issue by just not displaying the card based on the filter, that way the index remained correct:

   <div     cdkDropList 
            id="{{list.projectName}}" 
            [cdkDropListData]="list.products"
            class="list-droparea"
            (cdkDropListDropped)="drop($event, list)">
        <div    *ngFor="let product of list.products"
                class="card-dropable" 
                cdkDrag
<!--here-->     [class.item__hidden]="!product.productName.toLocaleLowerCase().includes(list.searchTerm.toLowerCase())"
                [class.item__moved]="product.originalProjectId !== list.id">
            <div class="row">
                <div class="col-12"><h6> {{product.productModelName}} </h6></div>
                <div class="col-12"><small class="m-0 secondary"> {{product.productName}}     </small></div>
                <div class="col-12" *ngIf="product.originalProjectId !== list.id">
                    <strong [innerHTML]="getProject(product.originalProjectId)"></strong>
                </div>
            </div>
        </div>
    </div>

And in the styles i have .item__hidden{ display:none }

1
votes

be sure to call: this.dtable.renderRows(); as this will update the destination.

1
votes

Here a better solution

In transferArrayItem replace

event.previousIndex

with

event.previousContainer.data.indexOf(event.item.data)

Example :

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