Drag&Dropって結構Webアプリだと当たり前になってきてるし、フロントサイドだとJqueryUIやReactなどライブラリを使用すればすぐできる世の中だと思います。ただ裏側(サーバサイド)の処理ってどう実装するんだっけと、ふと思い書いてみました。
まず、前提としてフロントだけで完結せず、サーバサイドの実装あるものとしてます。
初期状態(前提条件)
↓↓↓ 順序の情報をもってるテーブル ↓↓↓
※ここでは上記テーブルをT_○○と命名しておきます
※またorder_noでソートしたものを表示する
Drag&Dropの手順
- フロントサイドでDrag&Dropの操作をして、サーバサイドに以下の情報を送る。
・動かそうとしているorder_no (from_order_noと呼びます)
・動そうとしている先にいるitemのorder_no (to_order_noと呼びます) - from_order_noとto_order_noの間にあるorder_noを増減させる。
- 対象itemのorder_noをto_order_noで更新する。
パッと見、文字だけだと分かりづらいので、図で例を示します。
ex.)id=2をid=4, 5の間にDrag&Dropする。
つまり、id=2のorder_noを4で更新したい時
↓
id=2のorder_noを更新する前に、id=3, 4のorder_noを1減らす
↓
id=2のorder_noを4で更新する
の手順を実装していきます。
ただ今回は上から下へDrag&Dropをしました(from_order_no < to_order_no)が、下から上へとDrag&Dropした(from_order_no > to_order_no)時も同じようにfrom_order_noとto_order_noの間のorder_noを調整する必要があり、若干今回の例と異なります。
ここは考えてみてください...
実装
実装しちゃいます。
あ、言語はC#です。
/// <summary>
/// Drag&Dropのサーバサイド側の処理
/// </summary>
/// <param name="fromOrderNo">移動前のorder_no</param>
/// <param name="toOrderNo" >移動先のorder_no</param>
public void DragAndDrop(int fromOrderNo, int toOrderNo)
{
// SQLへ接続、Transactionの処理は今回省略します....
var command = new SqlCommand();
command.Connection = connection; // connectionは上で定義してください
var headOrderNo = fromOrderNo < toOrderNo ? (fromOrderNo + 1) : toOrderNo;
var tailOrderNo = fromOrderNo < toOrderNo ? toOrderNo : (fromOrderNo - 1);
var step = fromOrderNo < toOrderNo ? -1 : 1;
// fromOrderNoとtoOrderNoの範囲内のorderNoを調整する
IncrementTargetRangeOrderNo(command, headOrderNo, tailOrderNo);
// fromOrderNoとtoOrderNoを入れ替える
ReplaceOrderNo(command, fromOrderNo, toOrderNo);
// SQL接続終了の処理....
}
/// <summary>
/// 指定範囲内のorder_noを増減させる
/// </summary>
/// <param name="cmd">SqlCommand</param>
/// <param name="headOrderNo">orderNoの範囲指定の先頭</param>
/// <param name="tailOrderNo">orderNoの範囲指定の末尾</param>
/// <param name="step">増減数(マイナス値を入れれば減少数)</param>
private void IncrementTargetRangeOrderNo(SqlCommand cmd, int headOrderNo, int tailOrderNo, int step = 1)
{
cmd.CommandText = @"
UPDATE
T_◯◯
SET
order_no = order_no + @step
WHERE
order_no >= @head_order_no
AND
order_no <= @tail_order_no
";
cmd.Parameters.Add(new SqlParameter("@step", step));
cmd.Parameters.Add(new SqlParameter("@head_order_no", headOrderNo));
cmd.Parameters.Add(new SqlParameter("@tail_order_no", tailOrderNo));
cmd.ExecuteNonQuery();
}
/// <summary>
/// 指定したorder_noへ置き換える
/// </summary>
/// <param name="cmd">SqlCommand</param>
/// <param name="headOrderNo">orderNoの範囲指定の先頭</param>
/// <param name="tailOrderNo">orderNoの範囲指定の末尾</param>
private void ReplaceOrderNo(SqlCommand cmd, int fromOrderNo, int toOrderNo)
{
cmd.CommandText = @"
UPDATE
T_◯◯
SET
order_no = @to_order_no
WHERE
order_no = @from_order_no
";
cmd.Parameters.Add(new SqlParameter("@from_order_no", fromOrderNo));
cmd.Parameters.Add(new SqlParameter("@to_order_no", toOrderNo));
cmd.ExecuteNonQuery();
}
これでいけたかな?
以上です。