-->

Tạo menu nhiều cấp (Multi-Level Menus) trong ASP.NET Core MVC

Hôm nay mình sẽ hướng dẫn các bạn tạo menu nhiều cấp trong ASP.NET Core MVC, một chủ đề mà nhiều bạn rất mong mỏi khi mới làm quen với ASP.NET Core MVC.

Menu nhiều cấp, chẳng hạn như 2 cấp, 3 cấp,... có nhiều cách để xử lý, nhưng trong bài viết này, mình sẽ hướng dẫn các bạn tạo menu đa cấp mới 1 table trong database, nhưng vẫn đảm bảo phân cấp.

Với menu đa cấp, hay bạn có thể gọi là mega menu, với menu này ứng dụng rất nhiều trong bán hàng, hay một website chứa khá nhiều category.


Ok, và bây giờ chúng ta bắt đầu bài hướng dẫn.

Tiến hành

Bước 1: Tạo các thực thể với database được thiết kế như sau:

Trong code firts entity framwork core ta có các class sau để phục vụ cho việc Migration dữ liệu:

Entities:

public class CmsMegaMenu
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Slug { get; set; }
        public int? DisplayOrder { get; set; }
        public DateTimeOffset CreatedOn { get; set; }
        public DateTimeOffset? UpdatedOn { get; set; }

        public Status Status { get; set; }

        public List<CmsMegaMenuSub> CmsMegaMenuSub { get; set; }
    }

public class CmsMegaMenuSub
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Slug { get; set; }
        public int? DisplayOrder { get; set; }
        public DateTimeOffset CreatedOn { get; set; }
        public DateTimeOffset? UpdatedOn { get; set; }

        public Status Status { get; set; }
        public int MenuId { get; set; }

        public CmsMegaMenu CmsMegaMenu { get; set; }
        public List<CmsMegaMenuSubItem> CmsMegaMenuSubItem { get; set; }
    }

public class CmsMegaMenuSubItem
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Slug { get; set; }
        public int? DisplayOrder { get; set; }
        public DateTimeOffset CreatedOn { get; set; }
        public DateTimeOffset? UpdatedOn { get; set; }

        public Status Status { get; set; }
        public int MenuId { get; set; }

        public CmsMegaMenuSub CmsMegaMenuSub { get; set; }
    }


Configurations:

public class CmsMegaMenuConfiguration : IEntityTypeConfiguration<CmsMegaMenu>
    {
        public void Configure(EntityTypeBuilder<CmsMegaMenu> builder)
        {

            builder.ToTable("CmsMegaMenus");
            builder.HasKey(x => x.Id);

            builder.Property(x => x.Id).UseIdentityColumn();

            builder.Property(x => x.Status).HasDefaultValue(Status.Active);
        }
    }


public class CmsMegaMenuSubConfiguration : IEntityTypeConfiguration<CmsMegaMenuSub>
    {
        public void Configure(EntityTypeBuilder<CmsMegaMenuSub> builder)
        {

            builder.ToTable("CmsMegaMenuSubs");
            builder.HasKey(x => x.Id);

            builder.Property(x => x.Id).UseIdentityColumn();

            builder.Property(x => x.Status).HasDefaultValue(Status.Active);

            builder.HasOne(x => x.CmsMegaMenu).WithMany(x => x.CmsMegaMenuSub).HasForeignKey(x => x.MenuId);
        }
    }

public void Configure(EntityTypeBuilder<CmsMegaMenuSubItem> builder)
        {

            builder.ToTable("CmsMegaMenuSubItems");
            builder.HasKey(x => x.Id);

            builder.Property(x => x.Id).UseIdentityColumn();

            builder.Property(x => x.Status).HasDefaultValue(Status.Active);

            builder.HasOne(x => x.CmsMegaMenuSub).WithMany(x => x.CmsMegaMenuSubItem).HasForeignKey(x => x.MenuId);
        }



Bước 2: Khi đã xong các thực thể, ta tiến hành làm việc với các Controllers và Views:
Ta gọi phương thức sau:

public IActionResult Index()
{

      ViewBag.ListMegaMenu = _context.CmsMegaMenus.Where(n => n.Status == Status.Active)
                .Include(n => n.CmsMegaMenuSub)
                    .ToList();
      ViewBag.ListMegaMenuItem = _context.CmsMegaMenuSubs.Where(n => n.Status == Status.Active).Include(n => n.CmsMegaMenuSubItem).ToList();

      return View();
} 


Với View sau:

@model List<AlbayMart.Data.Entities.CmsMegaMenu>
<nav id="site-navigation" class="main-navigation sticky-active" role="navigation">
    <ul id="primary-menu" class="menu nav-menu" aria-expanded="false">
        <li id="menu-item-739" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-739 active">
            <a href="#" class="vertical-main"><i class="fa fa-bars pr-3" aria-hidden="true"></i>Danh mục sản phẩm</a>
            <ul class="sub-menu">

                @foreach (CmsMegaMenu menu1 in ViewBag.ListMegaMenu)
                {

                    if (menu1.CmsMegaMenuSub.Count() == 0)
                    {
                        <li id="menu-item-740" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-1455">
                            <a href="#"><i class="fa fa-fire pr-2"></i>@menu1.Name</a>
                        </li>
                    }
                    else
                    {

                        <li id="menu-item-740" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-740">
                            <a href="#"><i class="fa fa-male pr-2"></i>@menu1.Name</a>
                            <i class="fa fa-angle-right menu-icn-right" aria-hidden="true"></i>
                            <ul class="sub-menu sub-menu-megaz">
                                @foreach (CmsMegaMenuSub menu2 in menu1.CmsMegaMenuSub)
                                {

                                    <li id="menu-item-1454" class="menu-item menu-item-type-post_type menu-item-has-children menu-item-object-page menu-item-1454 megaz-menu-items">
                                        <a href="#" class="mega-tite">@menu2.Name</a>
                                        <ul class="sub-menu sub-megaz">
                                            @foreach (CmsMegaMenuSubItem menu3 in menu2.CmsMegaMenuSubItem)
                                            {
                                                <li class="menu-megaz">
                                                    <a href="#">@menu3.Name</a>
                                                </li>
                                            }
                                        </ul>
                                    </li>

                                }

                            </ul>
                        </li>
                    }

                }
            </ul>
        </li>
    </ul>
</nav>

Lời kết

Tạo menu phân cấp có nhiều hướng và cách làm khác nhau, và tất nhiên trong các bài sau sẽ làm một bài tips với hướng đi hoàn toàn khác.

Hy vọng 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?

8 comments

Post a Comment