Ryware / ngx-drag-and-drop-lists

Angular drag and drop component for lists
MIT License
49 stars 40 forks source link

Moving an item to index 0 gets inserted to index 1 #114

Closed Francisco-RP closed 1 year ago

Francisco-RP commented 1 year ago

Try dragging an item from any position other than the top, up to the top (index 0) of a list

expected: Item gets inserted at the very top of the list, pushing other items down

actual: items gets inserted at the 2nd position (index 1)

It's weirdly inconsistent, I can get it to work in a nested list sometimes

This can be seen happening right now on the demo linked to from your Readme: https://stackblitz.com/edit/ngx-drag-and-drop-lists/?file=src%2Fapp%2Fapp.component.ts

index-0

I think I know why it's happening, there's an issue with the calculation of this offset value: https://github.com/misha130/ngx-drag-and-drop-lists/blob/master/src/directives/dnd-list.ts#L162

let offset: number = this.nativeElement.children.length - 1 - this.dndModel.length;

The problem is that this.nativeElement.children includes a placeholder element which causes a classic off-by-1 issue

Screenshot 2023-06-09 at 2 09 16 PM

You probably need to filter out the placeholder element when checking children

So right now, when trying to drag to position 0, the offset value gets calculated to a value of -1

And when we get to this line: https://github.com/misha130/ngx-drag-and-drop-lists/blob/master/src/directives/dnd-list.ts#L162

let insertionPoint: number = index - offset;

index 0 minus offset -1 = 1(0 - -1 = 1)

And that's why anything trying to get inserted into index 0 keeps ended up at index 1

Francisco-RP commented 1 year ago

For anyone else experiencing this issue I have a temporary workaround using the dndInserted event to alter the model after inserted.

// (dndInserted)="onInsert($event, simpleList[0])"

public onInsert(event: DropEvent<any>, list: any[]) {
    const actualIndex = list.indexOf(event.item);
    if (event.index !== actualIndex) {
      const [item] = list.splice(actualIndex, 1);
      list.splice(event.index, 0, item);
    }
  }

See it in action here (I did not include it in the nested list) https://stackblitz.com/edit/ngx-drag-and-drop-lists-xbft7n/?file=src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.component.ts