Rails7 stimulusを使用してドラッグアンドドロップを実装する
- 作成日 2024.07.04
- rails
Ruby on Rails 7で、stimulusを使用してRails7 stimulusを使用してドラッグアンドドロップを実装するサンプルコードです。
目次
環境
- OS Ubuntu24.04
- rails 7.1.3
Stimulusのインストール
Rails 7では、Stimulusがデフォルトでセットアップされているため、追加のインストールは不要ですが、念のため以下のコマンドで確認します。
$ bundle exec rails stimulus:install
Scaffoldの作成
サンプルデータとして、Item
モデルを作成します。
$ rails generate scaffold Item name:string position:integer
$ rails db:migrate
db/seeds.rb
にいくつかのサンプルデータを追加します。
# db/seeds.rb
Item.create(name: "Item 1", position: 1)
Item.create(name: "Item 2", position: 2)
Item.create(name: "Item 3", position: 3)
以下のコマンドを実行してサンプルデータをデータベースに追加します。
$ rails db:seed
Stimulusコントローラーの作成と設定
Stimulusコントローラーを生成します。
$ rails generate stimulus Drag
生成されたコントローラーを以下のように編集します。
// app/javascript/controllers/drag_controller.js
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["item"]
connect() {
this.draggedElement = null;
}
dragstart(event) {
this.draggedElement = event.target;
event.target.style.opacity = 0.5;
}
dragend(event) {
event.target.style.opacity = "";
}
dragover(event) {
event.preventDefault();
}
drop(event) {
event.preventDefault();
if (event.target.classList.contains("dropzone")) {
event.target.style.background = "";
event.target.parentNode.insertBefore(this.draggedElement, event.target.nextSibling);
// Update positions in the backend
const itemIds = Array.from(this.itemTargets).map(item => item.dataset.id);
this.updatePositions(itemIds);
}
}
dragenter(event) {
if (event.target.classList.contains("dropzone")) {
event.target.style.background = "rgba(0, 0, 0, 0.1)";
}
}
dragleave(event) {
if (event.target.classList.contains("dropzone")) {
event.target.style.background = "";
}
}
updatePositions(itemIds) {
fetch("/items/update_positions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').getAttribute("content")
},
body: JSON.stringify({ item_ids: itemIds })
});
}
}
HTMLの設定
app/views/items/index.html.erb
を以下のように編集します。
// app/javascript/controllers/drag_controller.js
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["item"]
connect() {
this.draggedElement = null;
}
dragstart(event) {
this.draggedElement = event.target;
event.target.style.opacity = 0.5;
}
dragend(event) {
event.target.style.opacity = "";
}
dragover(event) {
event.preventDefault();
}
drop(event) {
event.preventDefault();
if (event.target.classList.contains("dropzone")) {
event.target.style.background = "";
event.target.parentNode.insertBefore(this.draggedElement, event.target.nextSibling);
// Update positions in the backend
const itemIds = Array.from(this.itemTargets).map(item => item.dataset.id);
this.updatePositions(itemIds);
}
}
dragenter(event) {
if (event.target.classList.contains("dropzone")) {
event.target.style.background = "rgba(0, 0, 0, 0.1)";
}
}
dragleave(event) {
if (event.target.classList.contains("dropzone")) {
event.target.style.background = "";
}
}
updatePositions(itemIds) {
fetch("/items/update_positions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').getAttribute("content")
},
body: JSON.stringify({ item_ids: itemIds })
});
}
}
コントローラーの編集
ドラッグアンドドロップによる位置の更新をサポートするために、ItemsController
を編集します。config/routes.rb
を以下のように編集します。
Rails.application.routes.draw do
resources :items do
collection do
post :update_positions
end
end
root "items#index"
end
app/controllers/items_controller.rb
を以下のように編集します。
# app/controllers/items_controller.rb
class ItemsController < ApplicationController
def index
@items = Item.order(:position)
end
def update_positions
params[:item_ids].each_with_index do |id, index|
Item.where(id: id).update_all(position: index + 1)
end
head :ok
end
# 他のアクション
end
スタイルの追加
ドラッグアンドドロップの視覚的なフィードバックを向上させるために、スタイルを追加します。
app/assets/stylesheets/application.css
に以下のスタイルを追加します。
.dropzone {
padding: 10px;
border: 1px solid #ccc;
margin-bottom: 5px;
cursor: move;
}
Railsサーバーの起動
最後に、Railsサーバーを起動して動作を確認します。
※自分の環境は外部からアクセスできるようにして起動してます。
$ rails s -b 0.0.0.0
ブラウザでhttp://localhost:3000
にアクセスすると、ドラッグアンドドロップが正しく動作することが確認できます。
-
前の記事
Dart リスト(配列)の最初の値を取得する 2024.07.03
-
次の記事
Oracle Database ファンクションの内容を確認する 2024.07.04
コメントを書く