勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

SortableJSを使ってデータの並べ替え&保存

  PHP jQuery MySQL JavaScript

あるシステムを拝見した際にtableタグ内に並んでいる項目をドラッグ&ドロップで並べ替えする機能があった。ブラウザからソースを確認するとjQuery UIのSortable機能を使っているっぽい。ただ、jQuery UIを利用しなくてもSortable.jsは個別で利用できるようなので以下に使い方のメモ。

 

やりたいこと

tableタグ内の項目をドラッグ&ドロップで入れ替えて「変更」等のボタンをクリックすると並び順がMySQLに保存され、保存された並び順で表示される機能を実装したい。

 

サンプル

https://taitan916.info/sample/sortable/

 

Sortable.js

以下からダウンロードする。

https://github.com/SortableJS/Sortable

もしくはCDNで以下のように呼び出しても良い。

<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>

 

ソース

<?php
//MySQL接続
$mysqli = new mysqli($dbhost, $dbuser, $dbpass, $dbname);
$mysqli->set_charset('utf8');

//並び順変更処理
if( $_POST['order'] ){
	$data = json_decode($_POST['order'], true);

	foreach( $data as $key => $val ){
		$sql = '
			UPDATE sort_table  
			SET `order` = "' . $mysqli->real_escape_string($val) . '"
			WHERE id = "' . $mysqli->real_escape_string($key) . '"
		';
		$row = $mysqli->query($sql);
	}

	//ページリロード防止用
	header('Location:./');
	exit();
}

$sql = '
	SELECT * 
	FROM sort_table 
	ORDER BY `order` ASC
';
$row = $mysqli->query($sql);
while ($rs = $row->fetch_array(MYSQLI_ASSOC)) {
	$data[$rs['id']] = $rs;
}
?>
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Sortable サンプル</title>
</head>
<body>
<link href="//stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="//stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>
<script type="text/javascript" src="//code.jquery.com/jquery-3.5.1.js"></script>
<style>
td{
	cursor: move;
}
</style>
<form action="./" method="post" id="order_form">
	<table>
		<tbody id="sort-table">
			<?php foreach( $data as $key => $val ){ ?>
				<tr class="id_<?php echo $val['id'];?>">
					<td><?php echo $val['order'];?></td>
					<td><?php echo $val['name'];?></td>
				</tr>
			<?php } ?>
		</tbody>
	</table>
	<input type="hidden" name="order" class="order" value="">
	<input type="submit" class="btn btn-success" value="順番を変更" onClick="return sortCheck();">
</form>
<script>
	//Sortable
	let table = document.getElementById('sort-table');
	Sortable.create(table);

	//並び順の処理
	function sortCheck(){
		let data = $('#sort-table > tr');
		let query = new Object();

		for( let i = 0; i < data.length; i++ ){
			//オブジェクトにkey = id / val = 並び順を格納
			query[data[i].attributes.class.value.replace('id_', '')] = i + 1;
		}

		//データをJSON化してinput="hidden"に格納
		$('.order').val(JSON.stringify(query));

		//フォーム送信
		$('#order_form').submit();

		//IEの二重送信防止用
		return false;
	}
</script>
</body>
</html>

query[data[i].attributes.class.value.replace('id_', '')]のところがちょっと気持ち悪いが、綺麗にまとめられなかった。

 

所感

今まで並び順変更機能を実装する場合、テキストボックス(input type="text")に数値を入力する形で実装していた。そうすると同じ数値を入力していた場合や、数値が入っていない場合はどうするかとか考える必要があったが、Sortable.jsを使うことでその辺りの作業は必要なくなりそう。

とはいえページングありのページだとテキストボックス形式を使うしかなさそう。あと、Sortable.jsの方がUI的に親切に思えるが、こちら側としてはJSを沢山使うとブラウザによって(特にIEは)挙動が異なったりするので、ブラウザ毎のチェックや不具合が発生した際の修正の手間を考えると、どちらの形式でいくのか悩ましいところ。

 - PHP jQuery MySQL JavaScript

  関連記事

エリア→都道府県→路線→駅名を連携する絞り込みセレクトメニューの設置方法

エリア→都道府県→路線→駅名のドリルダウン検索をプルダウン形式で設置したい。以前 ...

AjaxFileUploadで処理は実行できてもエラーが返る

AjaxFileUploadでPHPに通信し、サーバー側のPHPで処理は正常に実 ...

オリジナルのjQueryプラグインを作成する方法

オリジナルのjQueryプラグインを作ってみたかった。というのも大抵のものはググ ...

jQueryにて特定のIDが存在するかチェックし分岐処理する方法

jQueryにて特定のIDが存在するかチェックし分岐処理したいというケースがあっ ...

jQueryでAjax通信したデータをPHPで受け取り、zip化したファイルをダウンロードさせる方法

jQueryのAjaxで何らかのデータをPHP側に送信し、PHP側で当該データを ...