3

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

born2net
  • 24,129
  • 22
  • 65
  • 104

4 Answers4

2

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

Daniel Habenicht
  • 2,133
  • 1
  • 15
  • 36
  • THANK YOU SO MUCH! Yep, figured it was something of that nature, didn't update the original list with the right array, TX AGAIN!!!! – born2net Oct 25 '19 at 16:04
  • 1
    You are welcome, it's always the basic stuff that gets us :D – Daniel Habenicht Oct 25 '19 at 16:05
  • I tried to convert to Table with no luck.. any ideas on that? https://stackblitz.com/edit/angular-agf3kv-qhsmgp?file=app/cdk-drag-drop-disabled-sorting-example.css – born2net Oct 25 '19 at 18:31
  • 1
    Check the variables for the columns of each table – Daniel Habenicht Oct 25 '19 at 18:41
  • fixed the element.symbol. the issue is that the target does not accept the drop – born2net Oct 25 '19 at 18:50
  • really odd... simplified it to bare minimum with no luck: https://stackblitz.com/edit/angular-agf3kv-qhsmgp?file=app%2Fcdk-drag-drop-disabled-sorting-example.ts – born2net Oct 25 '19 at 19:42
  • [Edited] Here is a working prototype: https://stackblitz.com/edit/angular-9attms – Daniel Habenicht Oct 25 '19 at 20:14
  • You have to call `table.renderRows()` See here: https://stackoverflow.com/questions/53377450/reorder-mat-table-rows-with-angular-materials-drag-and-drop – Daniel Habenicht Oct 25 '19 at 20:20
  • 1
    This doesn't work though. 1) Filter the item, for example 'Tomatoes' 2) Drag and drop to the second list 3) Clear the filter 4) Observe that `Tomatoes` are still in the first list – Amarula Apr 23 '20 at 09:14
2

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 }

James D
  • 1,975
  • 2
  • 17
  • 26
2

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);
    }
}
Tinismo
  • 39
  • 6
1

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

born2net
  • 24,129
  • 22
  • 65
  • 104