3

在我的项目中,我有一个 Rails API 后端,我使用acts_as_list gem 和Vue 前端,我使用Vue Draggable 包。

拖动的行为有效,我看到一个 PUT 请求被发送到我的服务器。然而,发生了一些奇怪的事情:

场景 1: 我将一个项目从位置 1 拖到位置 2(所以它们基本上是触发器)。正在发送 PUT 请求,但未发生实际更新。

场景 2: 我将一个项目从位置 1 拖到位置 3。这意味着位置 2 应该向上移动到 1,2 应该向上移动到 1,并且 1 应该在 3 中(希望这有意义)。这很奇怪,因为有时我会在我的服务器上看到更新,但不是每次都发生。

我需要的是在拖动时更新整个列表。

待办事项列表.vue

<template>
    <div class="todos-container" v-if='trips.loaded'>
      <draggable 
        :list='todoList' 
        :options='{animation:150}'
        tag='ul' 
        class='list-group' 
        @change='changed(todoList, $event)'
      >
        <transition-group type='transition'>
          <li v-for='(todo, index) in todoList' :key='todo.id' class='list-group-item'>
            <v-icon class='drag-handle'>drag_handle</v-icon>
            <v-checkbox
              v-model="todoList[index].completed"
              :ripple='false'
              :label='`${todo.title}`'
              color='primary'
              @change='handleTodoClick(todo, index)'
            />
            <v-icon class='remove-todo' @click='handleTodoDelete(todo, index)'>close</v-icon>
          </li>

        </transition-group>
      </draggable>
    </div>
  </todo-list-styles>
</template>

<script>
  import { mapActions } from 'vuex';
  import draggable from 'vuedraggable';

  export default {
    props: {
      trips: {
        type    : Object,
      },
      index: {
        type    : Number,
        required: true,
      }
    },
    computed: {
      todoList() {
        return this.trips.data[this.index].todos;
      }
    },
    methods: {
      ...mapActions('trips', [
        'updateTodoPosition'
      ]),
      handleTodoClick: function(todo, index) {
        console.log('checked')
      },
      handleTodoDelete: function(todo, index) {
        console.log('clicked');
      },
      changed: function(todoList, $event) {
        const {oldIndex, newIndex} = $event.moved;
        const todo = todoList[newIndex];
        const payload = {
          oldIndex,
          newIndex,
          todo,
        };
        this.updateTodoPosition(payload);
      },
    },
    components: {
      draggable,
    },
  }
</script>

参数

Started PUT "/2/update_todo_position" for 127.0.0.1 at 2019-05-13 08:46:09 -0500
Processing by V1::TripsController#update_todo_position as */*
  Parameters: {"oldIndex"=>0, "newIndex"=>2, "todo"=>{"id"=>2, "title"=>"Book Car Rental", "completed"=>true, "position"=>2}, "todo_id"=>"2", "trip"=>{"oldIndex"=>0, "newIndex"=>2, "todo"=>{"id"=>2, "title"=>"Book Car Rental", "completed"=>true, "position"=>2}}}
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  TodoItem Load (0.2ms)  SELECT  "todo_items".* FROM "todo_items" WHERE "todo_items"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
   (0.2ms)  BEGIN
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  UpcomingHike Load (0.3ms)  SELECT  "upcoming_hikes".* FROM "upcoming_hikes" WHERE "upcoming_hikes"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
   (0.2ms)  COMMIT
Completed 200 OK in 5ms (ActiveRecord: 1.1ms)

trips_controller.rb

module V1
  class TripsController < ApplicationController

    ...

    def update_todo_position
      # TODO: Figure out why position being saved is incorrect
      todo = TodoItem.find(params[:todo][:id])
      todo.update!(position: params[:newIndex])
      head :ok
    end

    ...

  end
end
4

1 回答 1

0

Ended up going a route that I'm not proud of, but works. From my frontend I'm sending over the entire newly ordered list. Then in my controller, I'm rolling through each one and individually updating their position. Definitely not the VueDraggable recommended way of doing it, and absolutely not an efficient way of handling it in my controller:

vue component method:

changed: function(todoList, $event) {
        const {newIndex} = $event.moved;
        const todo = todoList[newIndex];
        const newListOrder = JSON.stringify(this.todoList.map(todo => todo.id));
        const payload = {
          todo,
          newListOrder,
        }
        this.updateTodoPosition(payload);
      },

controller:

def update_todo_position
      newListIds = params[:_json]
      newListIds.each.with_index(1) do |todo, index|
        todo = TodoItem.find(todo)
        todo.update(position: (index))
      end
      head :ok
    end

If anyone has any suggestions, I'd love to hear it!

于 2019-05-15T13:35:40.133 回答