ruby-on-rails - 如何使用 Sortable.js、acts_as_list 和 Stimulus 为nested_attributes 获得正确的位置
问题描述
我正在尝试使用nested_attributes实现“拖放排序列表”(https://gorails.com/episodes/rails-drag-and-drop-sortable )。
不幸的是,我弄错了:position
。即使总共应该只有三个位置,它也会从 2 跳到 5 到 7。
我认为问题在于隐藏的输入标签也被计算在内。如果这是主要问题,有什么办法解决吗?
// config/routes.rb
resources :recipes, except: :index do
resources :steps do
resource :step_position, only: :update
end
end
// app/views/recipes/_form.html.erb
<div data-controller="sortable" data-sortable-url="/recipes/:recipe_id/steps/:id/step_position">
<%= f.fields_for :steps, @recipe.steps.order(position: :asc) do |step| %>
<div data-id="<%= step.object.id %>">
<%= step.text_area :description %>
</div>
<% end %>
</div>
// app/javascript/controllers/sortable_controller.js
import { Controller } from "stimulus";
import Rails from "@rails/ujs";
import { Sortable } from "sortablejs";
export default class extends Controller {
connect() {
this.sortable = Sortable.create(this.element, {
onEnd: this.end.bind(this),
});
}
end(event) {
let id = event.item.dataset.id;
let data = new FormData();
data.append("position", event.newIndex + 1);
Rails.ajax({
url: this.data.get("url").replace(":id", id),
type: "PATCH",
data: data,
});
}
}
// app/controllers/step_positions_controller.rb
class StepPositionsController < ApplicationController
def update
@step = Step.find(params[:step_id])
authorize @step.recipe
@step.insert_at(params[:position].to_i)
head :ok
end
end
解决方案
首先看一下传递给服务器的参数。这些看起来好吗?如果没有,那么 javascript 可能是罪魁祸首。
其次,insert_at
在这种情况下,它不是工作的最佳工具。如果您想显式设置位置而不受回调等干扰...我通常where(:id => id).update_all(:position => the_position)
在列表中的每个元素上使用(前提是您知道您的参数中包含所有元素。
最好的解决方案是让 javascript 向您发送要移动的项目以及您希望它在列表中的位置,然后只需将位置列设置为该值,acts_as_list
并将为您洗牌。唯一的缺点是来自其他用户的并发更新。如果是这种情况,您的列表将不同步。
推荐阅读
- next.js - 带有 NextJs 的 react-intl 的运行时要求 - 如何填充?
- angular - 如何在打字稿延迟后显示模态
- reactjs - 在 konva 中更改裁剪矩形之外的不透明度
- typescript - 打字稿:[编译时间]具有“as const”类型缩小的可写(-可读)数组/对象
- database - Flutter 从 Friebase 实时数据库中获取数据
- python - 如何使用 python 电报机器人获取旧的消息 ID?
- laravel - Laravel/Livewire:在模型路由绑定上使用 withTrashed() 以显示已删除的记录
- c - 在简化的shell程序中,程序使用了两个chars数组,如下图(在userin.c代码中)
- vue.js - Vue - v-for 修改值
- google-chrome - 火狐 - webRequest.onBeforeSendHeaders