-->

Sort table rows sử dụng Drag & Drop trong ASP.NET Core MVC

Chúng ta thường tổ chức database có trường DisplayOrder hoặc SortOrder, và ta dùng nó một cách thủ công là tự gán giá trị 123456789 rồi sắp xếp tăng dần, giảm dần. 


Ok, ở đây chúng ta không làm vậy, và hôm nay sẽ là một hướng dẫn cách sắp xếp giá trị bằng cách kéo thả đến vị trí mong muốn, sử dụng jQuery UI kết hợp Ajax trong ASP.NET Core MVC.


Tiến hành sử dụng Code First Migration

Thứ tự sắp xếp chúng ta sẽ lưu vào database nên việc trước tiên ta phải tạo thực thể và kết nối database.

Bước 1: Tạo project ASP.NET Core Web Application sử dụng MVC mới.

Bước 2: Cài đặt các NuGet Package sau:
  • Microsoft.EntityFrameworkCore 
  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.EntityFrameworkCore.Tools

Bước 3: Cấu hình chuỗi kết nối tới SQL Server trong appsetting.json:

"ConnectionStrings": {
    "ConnectionString": "Server=CNPM-PC\\SQLEXPRESS;Database=DbMenu;Trusted_Connection=True;MultipleActiveResultSets=true"
  },


Bạn cần chú ý đến Server name và tên database để thay đổi cho phù hợp.

Bước 4: Tạo các lớp sau trong thư mục Models:
Menu.cs:

    public class Menu
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int SortOrder { get; set; }
    }

DataDbContext.cs:

    public class DataDbContext : DbContext
    {
        public DataDbContext(DbContextOptions<DataDbContext> options)
               : base(options)
        {

        }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            // Đặt khóa chính
            modelBuilder.Entity<Menu>().HasKey(s => s.Id);
        }
        public DbSet<Menu> Menus { get; set; }
    }

Bước 5: Ta vào Startup.cs và tìm đến phương thức ConfigureServices() và thêm đoạn code sau bên trong:

services.AddDbContext<DataDbContext>(options =>
         options.UseSqlServer(
                Configuration.GetConnectionString("ConnectionString")));

Bước 6: Vào Tools > NuGet Package Manager > NuGet Package Console và thực thi lần lượt 2 command sau: 
  • Add-Migration InitialCreate 
  • Update-database


Sort table rows sử dụng Drag & Drop

Bước 1: Tạo mới controller (empty) với tên là MenusController.cs với code sau:

[Route("home/menu")]
    public class MenusController : Controller
    {
        private readonly DataDbContext _context;

        
        public MenusController(DataDbContext context)
        {
            _context = context;
        }

        // GET: Menus
        [HttpGet]
        [Route("index")]
        public async Task<IActionResult> Index()
        {
            return View(await _context.Menus.OrderBy(m => m.SortOrder).ToListAsync());
        }

        // POST: Menus
        [HttpPost]
        [Route("index")]
        public ActionResult Index(int[] sortId)
        {
            int order = 1;
            foreach (int id in sortId)
            {
                Menu menu = _context.Menus.Find(id);
                menu.SortOrder = order;
                _context.SaveChanges();
                order += 1;
            }
            return View(_context.Menus.OrderBy(p => p.SortOrder).ToList());
        }

        [Route("order")]
        public ActionResult UpdateItem(string itemIds)
        {
            int count = 1;
            List<int> itemIdList = new List<int>();
            itemIdList = itemIds.Split(",".ToArray(), StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList();
            foreach (var itemId in itemIdList)
            {
                try
                {
                    var item = _context.Menus.Where(x => x.Id == itemId).FirstOrDefault();
                    item.SortOrder = count;
                    _context.Menus.Update(item);
                    _context.SaveChanges();
                }
                catch (Exception)
                {
                    continue;
                }
                count++;
            }
            _context.SaveChanges();
            return Json(itemIdList);
        }

    }

Ở đây, chúng ta sử dụng phương thức “UpdateItem” nhận tham số và tìm và sắp xếp theo danh sách và hiển thị ra view và cập nhật cơ sở dữ liệu. 

Bước 2: Add view cho method Index trong Views/Menus/Index.cshtml với code sau:

@model IEnumerable<DragDropSort.Models.Menu>

@{
    ViewData["Title"] = "Index";
}

@section Scripts {

    <style>
        tr:hover {
            background: #fafafa;
        }
    </style>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

    <script>
        $(document).ready(function () {
            $("#sortable").sortable({
                update: function (event, ui) {
                    var itemIds = "";
                    $("#sortable").find(".orderLine").each(function () {
                        var itemId = $(this).attr("data-sortid");
                        itemIds = itemIds + itemId + ",";
                    });
                    $.ajax({
                        url: '/home/menu/order',
                        data: { itemIds: itemIds },
                        type: 'POST',
                        success: function (data) {
                            alert("sort: " + data);
                        },
                        error: function (xhr, status, error) {

                        }
                    });

                }
            })

        })
    </script>
}

<h1>Index</h1>

<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Name)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.SortOrder)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody id="sortable">
        @foreach (var item in Model)
        {
            <tr>
                <td class="orderLine" id="sort@(item.Id)" data-sortid="@(item.Id)">
                    @Html.DisplayFor(modelItem => item.Name)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.SortOrder)
                </td>
                <td>
                    <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
                    <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
                    <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
                </td>
            </tr>
        }
    </tbody>
</table>


Rebuild solution và xem kết quả. 

Kết quả


Lời kết

Nếu bạn không tự động lưu mà thay đó sẽ dùng button để save các action, thì bạn hãy sử dụng onchange trong jQuery, hãy tìm hiểu và custom theo ý bạn muốn.

Các bước thực hiện rất đơn giản. Mong bài viết có ích với bạn.

Chúc các bạn thành công!

By Hiếu Quốc

Có lẽ bạn thích?

1 comment

Post a Comment