Сортируемый JS ломается при частичном рендеринге htmx

Я пытаюсь реализовать сортируемый список с перетаскиванием, используя SortableJS и htmx. У меня все работает, но после перетаскивания первого элемента (и повторного рендеринга частичного списка) я больше не могу использовать функцию перетаскивания. Когда часть не перерисовывается, функция перетаскивания работает как ожидалось. Я пробовал использовать htmx.on("htmx:load",..., а также поместить скрипт в частицу.

Я использовал diff для проверки различий между html до и после отрисовки частичной версии, и, насколько я могу судить, единственным различием за пределами переупорядоченного списка является токен csrf.

Любая помощь будет принята с благодарностью!

Из файла views.py:

def sort(request):
    event_pks_order = request.POST.getlist('event_order')
    events=[]
    for idx,event_pk in enumerate(event_pks_order,start=1):
        event = Event.objects.get(pk=event_pk)
        event.event_number = idx
        event.save()
        events.append(event)

    return render(request,'timing/partials/eventlist.html',{'events':events})

From eventlist.html:

<form class="sortable list-group" hx-trigger="end" hx-post="{% url 'sort' %}" hx-target="#event-list">
  {% csrf_token %}
  <div class="htmx-indicator">Updating...</div>
  {% for event in events %}
  <div>
    <input type="hidden" name="event_order" value="{{event.pk}}"/>
    <li class="list-group-item">{{event.event_number}} {{event.event_name}}
    </li>
  </div>
  {% endfor %}
</form>

Из base.html:

  <script>

    document.body.addEventListener('htmx:configRequest', (event) => {
        event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
    })

    htmx.onLoad(function(content) {
      var sortables = content.querySelectorAll(".sortable");
      for (var i = 0; i < sortables.length; i++) {
        var sortable = sortables[i];
        new Sortable(sortable, {
            animation: 150,
            ghostClass: 'blue-background-class'
        });
      }
    })

  </script>

Думаю, SortableJS выполняет некоторую инициализацию HTML.

Так что в первый раз все работает нормально, но новый HTML, который подставляется htmx, не инициализируется.

Это распространенный подводный камень.

Случайно использую тот же пример, что и вы: sortable :-)

Вот документация по этому поводу: https://htmx.org/docs/#3rd-party

В htmx вместо этого используется функция htmx.onLoad, и вы выбираете только из нового загруженного содержимого, а не из всего документа:

htmx.onLoad(function(content) {
    var sortables = content.querySelectorAll(".sortable");
    for (var i = 0; i < sortables.length; i++) {
      var sortable = sortables[i];
      new Sortable(sortable, {
          animation: 150,
          ghostClass: 'blue-background-class'
      });
    }
})

Это гарантирует, что при добавлении нового содержимого в DOM с помощью htmx, сортируемые элементы будут правильно инициализированы.

Решает ли это ваш вопрос?

Вернуться на верх