使用 jQuery UI 的 sortable 对数据项进行拖拽排序(ASP.NET MVC 示例)
本文发布于 6 年前,部分内容可能已经失去参考价值。
制作类似下图中的拖拽排序功能:
1. 首先数据库该表中添加字段 sort,类型为 double(MySQL 中为 double(0, 0))。
2. 页面输出绑定数据(以 ASP.NET MVC 控制器为例):
public ActionResult EditSort()
{
if (!zConsole.Logined) { return RedirectToAction("", "SignIn", new { redirect = Request.Url.OriginalString }); }
db_auto2018Entities db = new db_auto2018Entities();
return View(db.dt_dealer.Where(c => c.enabled).OrderBy(c => c.sort));
}
这里可以加条件列出,即示例中 enabled == true 的数据。
3. 前台页面引用 jQuery 和 jQuery UI。
4. 使用 <ul /> 列出数据:
<ul id="sortable" class="list-group gutter list-group-lg list-group-sp">
@foreach (var d in Model)
{
<li class="list-group-item" draggable="true" data-id="@d.id">
<span class="pull-left"><i class="fa fa-sort text-muted fa m-r-sm"></i> </span>
<div class="clear">
【id=@d.id】@d.name_full
</div>
</li>
}
</ul>
5. 初始化 sortable,当拖拽结束时保存次序:
<script>
var url_SaveSort = '@Url.Action("SaveSort")';
</script>
<script>
$("#sortable").sortable({
stop: function (event, ui) {
// console.log('index: ' + $(ui.item).index())
// console.log('id: ' + $(ui.item).data('id'))
// console.log('prev_id: ' + $(ui.item).prev().data('id'))
$.post(url_SaveSort, {
id: $(ui.item).data('id'),
prev_id: $(ui.item).prev().data('id')
}, function (json) {
if (json.result.success) {
// window.location.reload();
} else {
toastr["error"](json.result.info);
}
}, 'json');
}
});
$("#sortable").disableSelection();
</script>
这里回传到服务端的参数为:当前项的 id 值、拖拽后其前面一项的 prev_id 值(若移至首项则 prev_id 为 undefined)。
不使用 $(ui.item).index() 是因为,在有筛选条件的结果集中排序时,使用该索引值配合 LINQ 的 .Skip 会引起取值错误。
6. 控制器接收并保存至数据库:
[HttpPost]
public ActionResult SaveSort(int id, int? prev_id)
{
if (!zConsole.Logined)
{
return Json(new { result = new { success = false, msg = "请登录后重试!" } }, JsonRequestBehavior.AllowGet);
}
db_auto2018Entities db = new db_auto2018Entities();
dt_dealer d = db.dt_dealer.Find(id);
// 拖拽后其前项 sort 值(若无则 null)(此处不需要加 enabled 等筛选条件)
double? prev_sort = prev_id.HasValue
? db.dt_dealer.Where(c => c.id == prev_id).Select(c => c.sort).Single()
: null as double?;
// 拖拽后其后项 sort 值(若无前项则取首项作为后项)(必须强制转化为 double?,否则无后项时会返回 0,导致逻辑错误)
double? next_sort = prev_id.HasValue
? db.dt_dealer.Where(c => c.sort > prev_sort && c.id != id).OrderBy(c => c.sort).Select(c => (double?)c.sort).FirstOrDefault()
: db.dt_dealer.Where(c => c.id != id).OrderBy(c => c.sort).Select(c => (double?)c.sort).FirstOrDefault();
if (prev_sort.HasValue && next_sort.HasValue)
{
d.sort = (prev_sort.Value + next_sort.Value) / 2;
}
if (prev_sort == null && next_sort.HasValue)
{
d.sort = next_sort.Value - 1;
}
if (prev_sort.HasValue && next_sort == null)
{
d.sort = prev_sort.Value + 1;
}
db.SaveChanges();
return Json(new { item = new { id = d.id }, result = new { success = true } });
}
需要注意的是,当往数据库添加新项时,必须将 sort 值设置为已存在的最大 sort 值 +1 或最小 sort 值 -1。
var d = new dt_dealer
{
name_full = "新建项",
sort = (db.dt_dealer.Max(c => (double?)c.sort) ?? 0) + 1,
};
可能相关的内容