Как обработать перетаскивание между несколькими списками, используя Sortable jS и activ_as_list gem? - PullRequest
0 голосов
/ 31 марта 2020

Я полтора дня искал решение.

У меня есть несколько таблиц (категорий), которые позволяют пользователю перетаскивать каждую строку (элемент), чтобы изменить порядок расположения каждого элемента в этой таблице (категория). Я использую Sortable JS для обработки перетаскивания, и у меня так, чтобы переупорядочение в той же категории работало.

На моем бэкэнде у меня есть Rails API который использует Jbuilder для возврата JSON, и я использую activ_as_list gem , чтобы обработать позиции для меня.

У меня возникают проблемы с выяснением, как обрабатывать переупорядочение при перетаскивании Пункт из категории A в категорию B. Я считаю, что проблема заключается в действиях контроллера и моей неспособности найти решение для получения обновлений для нескольких категорий, а затем вернуть позиции обновленной категории с помощью Jbuilder. Некоторая помощь будет принята с благодарностью!

ItemsList. vue

    <script>
        methods: {
            async dragReorder({ item, to, from, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, clone, pullMode }) {

            // item that was dragged
            const draggedItem = JSON.parse(item.getAttribute('data-item'));

            // initial payload
            const payload = {
              category_id: draggedItem.category_id,
              category_item_id: draggedItem.pivot.id,
              item_id: draggedItem.id,
              new_index: newIndex + 1,
              user_id: this.user.id,
            };

            const newCategory = JSON.parse(to.getAttribute('data-category'));

            // if item is dragged to new category
            if (pullMode) payload.new_category_id = newCategory;

            await categoryService.updatePosition(payload);
          },
        },
        mounted() {
          this.$nextTick(() => {
            const tables = document.querySelectorAll('.items-table-container');
            tables.forEach(table => {
              const el = table.getElementsByTagName('tbody')[0];
              Sortable.create(el, {
                animation: 150,
                direction: 'vertical',
                easing: 'cubic-bezier(.17,.67,.83,.67)',
                group: 'items-table-container',
                onEnd: this.dragReorder,
              });
            });
          })
        },
    </script>

category.rb

    class Category < ApplicationRecord
      has_many :categories_items, -> { order(position: :asc) }
      has_many :items, through: :categories_items, source: :item

      accepts_nested_attributes_for :items
    end

category_item.rb

    class CategoriesItem < ApplicationRecord
      belongs_to :category
      belongs_to :item

      acts_as_list scope: :category
    end

item.rb

    class Item < ApplicationRecord
      has_many :categories_items
      has_many :categories, through: :categories_items, source: :category
    end

ateg_controller.rb

    def update_position
       item = CategoriesItem.find_by(category: params[:category_id], item: params[:item_id])

       # if item was moved to new category
       categories = []
       if params[:new_category_id]
          item.update(category_id: params[:new_category_id])
          Item.find(params[:item_id]).update(category_id: params[:new_category_id])
          item.insert_at(params[:new_index]) unless !item
          categories << Category.find(params[:category_id])
          categories << Category.find(params[:new_category_id])
        else
          item.insert_at(params[:new_index]) unless !item
          categories << Category.find(params[:category_id])
        end
        @categories = categories
    end

update_position. json .jbuilder

    json.array! @categories do |category|
      json.(category, :id, :name, :created_at, :updated_at)
      json.categories_items category.categories_items do |category_item|
        json.(category_item, :id, :category_id, :item_id, :created_at, :updated_at, :position)
      end
    end

Ответы [ 2 ]

1 голос
/ 01 апреля 2020

acts_as_list позволяет вам установить новый параметр области и положение элемента списка, затем просто сохранить элемент, и элемент будет перемещен из старой области в новую область в желаемой позиции автоматически (используя after_save обратные вызовы).

В этом отношении вы должны просто сделать это, а затем заново извлечь элементы в каждой из двух ваших областей и вернуть их на внешний интерфейс для обновления дисплея.

0 голосов
/ 01 апреля 2020

Наконец-то что-то работает, вот мой рабочий код:

    def update_position
      @categories = []

      ## if item moved to new scope ##
      if params[:new_category_id] 
        @category_item.update(category_id: params[:new_category_id])
        @category_item.insert_at(params[:new_index])
        @categories << Category.find(params[:new_category_id])
        @categories << Category.find(params[:category_id])

      ## else if item was moved within same scope ##
      else
        @category_item.insert_at(params[:new_index])
        @categories << Category.find(params[:category_id])
      end

      @categories
      render :index
    end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...