Sarahbe
Sarahbe

Reputation: 203

Angular Drag and drop with filter

I have an Angular application. which contains two drag and drop lists that are working fine. I want to add a filter to search for items inside the lists. The problem is when I filter items, the function transferArrayItem will use the wrong index and this is why it will move the wrong item.
I have added a stackblitz code to show the problem. To reproduce the problem please follow the steps:

  1. over the first list click search and type number 2
  2. try to move the item to the second list, it will move the item 1.

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

Upvotes: 2

Views: 2454

Answers (2)

Sarahbe
Sarahbe

Reputation: 203

I finally found a way to solve the issue with the cleanest code. I am using id with cdkDropList to know the source list, then I am transferring the item manually instead of using the transferArrayItem function provided by cdkDragDrop.

the full code is in
https://stackblitz.com/edit/angular-htpgvx?file=src%2Fapp%2Fapp.component.ts

Upvotes: 1

Alan Yu
Alan Yu

Reputation: 1542

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

You need to update the original a/b object after dropping item from container to another container. So It's not possible to use search-box component to do so.

app.component.html, I added <input> and removed <app-search-box>, added id to <div cdkDropList>

<input
  #search_a
  type="text"
  class="form-control"
  placeholder="Search"
  aria-label="Search"
  aria-describedby="basic-addon1"
/>

<div
  cdkDropList
  [cdkDropListData]="selectedList"
  class="example-list"
  (cdkDropListDropped)="dropItem($event)"
  id="a_drop_list"
>

app.component.ts, I added code to listen input keydown event

fromEvent(this.search_a.nativeElement, 'keydown')
  .pipe(
    debounceTime(550),
    map(x => x['target']['value'])
  )
  .subscribe(value => {
    this.updateFilter_a(value);
  })

Added updateFilter function , it trigger when input keydown

  updateFilter_a(val: any) {
    this.selectedList = [];
    this.selectedList = a.filter(v => v.title.indexOf(val)>= 0 || v.description.indexOf(val) >= 0);
  }

Modified dropItem(added code to delete item in a/b object when user moved item from container to another container)

  dropItem(event: CdkDragDrop<any[]>) {
    if (event.previousContainer !== event.container) {
      transferArrayItem(
        event.previousContainer.data,
        event.container.data,
        event.previousIndex,
        event.currentIndex
      );

  //dropped item id
  const delete_id = event.container.data[event.currentIndex].id;

  //item drop to a_drop_list
  if(event.container.id === 'a_drop_list') {
    //find object b item index when id == device_id
    var index = b.findIndex(function(o){
      return o.id === delete_id;
    })
    //delete item match id == device_id in obejct b
    if (index !== -1) b.splice(index, 1);
  } else if(event.container.id === 'b_drop_list') {
    var index = a.findIndex(function(o){
      return o.id === delete_id;
    })
    if (index !== -1) a.splice(index, 1);
  }
}

Upvotes: 0

Related Questions