Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong newIndex when in nested dom-repeat list #6

Open
JaySunSyn opened this issue Jul 23, 2015 · 1 comment
Open

Wrong newIndex when in nested dom-repeat list #6

JaySunSyn opened this issue Jul 23, 2015 · 1 comment

Comments

@JaySunSyn
Copy link

Sometimes when dragging items down, the event shows a newIndex of 0 which is the wrong index.
It comes most often when dragging the first element to the button of the same group.

<template is="dom-repeat" id="camerasList" items="{{cameras}}">
  <!-- groups -->
  <p>{{item.group.name}}</p>
  <sortable-list id="{{item.group.id}}" group="grouped" animation="150">

    <template is="dom-repeat" items="{{item.cams}}">
      <!-- cams -->
      <div id="{{item.id}}">{{item.name}}</div>
    </template>

  </sortable-list>
</template>
@davidmaxwaterman
Copy link

davidmaxwaterman commented Jan 11, 2020

While not quite the same as what you have, I have struggled a lot when combining sortable-list with dom-repeat.

I have found that dom-repeat keeps a reference to each of the sortable-items and it expects them to remain in that order. Sortable-list, of course, changes the order.
So, my solution is to, in the sortEnd handler:

  1. record the new order of the sorted items,
  2. put the items back into the order dom-repeat expects them to be,
  3. update the dom-repeat 'models' of the sorted items to the new order, and then let dom-repeat sort them.

Something like this:

  <sortable-list id="sortableList" sortable=".sort-item" on-sort-end="_onSortEnd">
    <template id="domRepeat" is="dom-repeat" items="[[_myItems]]" sort="_sortItems" observe="sortOrder">
      <div class="sort-item">[[item.sortOrder]]</div>
    </template>
  </sortable-list>

  _onSortEnd(event) {
    const {newIndex, oldIndex} = event.detail;
    const items = this.$.sortableList.querySelectorAll('.sort-item');
    const order = items.map((item) => item.sortOrder);

    // put the element back in the order dom-repeat expects them to be
    {
      const parent = this.$.sortableList;
      if (oldIndex < newIndex) {
        parent.insertBefore(items[newIndex], items[oldIndex]);
      } else {
        parent.insertBefore(items[newIndex], items[oldIndex].nextSibling);
      }
    }

    // update _myItems to reflect the new order
    {
      const newMyItems = this._myItems;
      newMyItems.sort((a,b) => order.indexOf(a.sortOrder) - order.indexOf(b.sortOder));
      this.set('_myItems', newMyItems);
    }

    // update the dom-repeat model
    const domRepeat = this.$.domRepeat;
    items.forEach((item, index) => {
      const model = domRepeat.modelForElement(item);
      model.set('item', {...model.item, sortOrder:index});
    });
  }

I probably made some mistakes there so it'll still need some fiddling, but yeah.

FWIW, I use sortable-list in two places, and I gave up trying to find the 'correct' solution in my first attempt and instead dropped dom-repeat altogether and instead just managed the list of items myself, which worked fine. I consider the above technique better, though, for some reason.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants