Khóa học Newnet Framework

Bài 6: Quản lý Menu - Module Menu

MENU là thành phần quan trọng trong website, giúp điều hướng nhanh chóng đến các trang quan trọng giúp người dùng dễ dàng tiếp cận đến các thông tin ta muốn truyền tải. Với mỗi giai đoạn, ta sẽ có những chiến dịch khác nhau giúp trang web tối ưu hơn, tăng khả năng tiếp cận đến khách hàng. Việc cập nhật thanh điều hướng (menu) xảy ra thường xuyên. Không chỉ menu ở đầu trang, còn có những menu ở cuối trang hoặc một số nơi khác. Module menu sinh ra giải quyết bài toán này.

MENU

Data menu được lưu trong cache nên chúng ta không cần quá lo việc quản lý menu làm giảm hiệu năng của website.

RENDER

Quản lý menu nằm bên trong tab Giao diện  trong trang quản trị. Sau khi tạo menu xong, ta sẽ nhận được menu key, ta paste menu key này vào nơi mà mình muốn hiển thị:

{!! FrontendMenu::render('main-menu') !!}	

Khi khai báo như này, hệ thống sẽ lấy giao diện mặc định được cung cấp. Giả sử như bạn không thích thì có thể thay đổi được, bằng cách truyền vào blade view làm tham số thứ 2 của hàm render

{!! FrontendMenu::render('main-menu', 'component.menu') !!}	

file menu.blade.php sẽ có biến $items là mảng các item của menu.

<ul class="list-unstyled mb-0 d-lg-flex align-items-center justify-content-start" id="hasMenu">
    @foreach($items as $item)
    <li>
        <a href="{{ $item->url }}" target="{{ $item->target }}">
            {!! $item->icon !!} {{ $item->label }}
            @if ($item->children->count())
                <i class="fal fa-angle-down"></i>
            @endif
        </a>
        @if ($item->children->count())

        <ul class="list-unstyled mb-0">
            @foreach($item->children as $child)
            <li>
                <a href="{{ $child->url }}" target="{{ $child->target }}">
                    {!! $child->icon !!}{{ $child->label }}
                    @if ($child->children->count())
                        <i class="fal fa-angle-right"></i>
                    @endif
                </a>
                @if ($child->children->count())
                <ul class="list-unstyled mb-0">
                    @foreach($child->children as $subChild)
                    <li>
                        <a href="{{ $subChild->url }}" target="{{ $subChild->target }}">
                            {!! $subChild->icon !!}{{ $subChild->label }}
                        </a>
                    </li>
                    @endforeach
                </ul>
                @endif
            </li>
            @endforeach
        </ul>
        @endif
    </li>
    @endforeach
</ul>

có thể tham khảo thêm các hàm bên trong model MenuItem

Vị trí menu có thể thay đổi dễ dàng bằng việc kéo thả.

BUILDER

Khi tạo menu item, ta có thể thấy mục Builder Type có các giá trị: link, trang, danh mục bài viết. Và có thể chọn chính xác trang nào hay danh mục nào.

Giả sử ta phát triển thêm module bán hàng, chúng ta muốn hiển thị các danh mục lên menu. Mặc dù Menu Builder hỗ trợ type link (nhập đường dẫn vào) nhưng khá mất công phải tìm đến đường dẫn đó. Chúng ta có thể khai báo để Menu Buider nạp vào.

Ở đây chúng ta sẽ khai báo cho phần danh mục bài viết trong Module CMS. Muốn dùng cái nào thì viết trong module đó cho dễ quản lý:

Tạo folder MenuBuilders bên trong src:

<?php

namespace Newnet\Cms\MenuBuilders;

use Illuminate\Support\Facades\Route;
use Newnet\Cms\Models\Category;
use Newnet\Menu\MenuBuilders\BaseFrontendMenuBuilder;

class CategoryMenuBuilder extends BaseFrontendMenuBuilder
{
    public function getTitle()
    {
        return __('cms::menu-builder.category');
    }

    public function getViewName()
    {
        return 'cms::menu-builder.category';
    }

    public function getFrontendUrl()
    {
        try {
            if ($id = $this->args['id']) {
                return Category::find($id)->url;
            }
        } catch (\Exception $e) {}

        return '#';
    }

    public function isActive()
    {
        $itemId = $this->args['id'] ?? null;
        $routeId = Route::current()->parameter('id');
        $routeName = Route::current()->getName();
        if ($routeName === 'cms.web.category.detail' && $routeId == $itemId) {
            return true;
        }

        return false;
    }
}
  • getTitle: tên hiển thị khi chọn builder type
  • getViewName: sẽ sử dụng 1 template và ta chỉ thay đổi label và options bên trong nó để load dữ liệu ra thôi
@sumoselect([
    'name' => 'menu_builder_args[id]',
    'label' => __('cms::menu-builder.category'),
    'options' => get_cms_category_menu_builder_options(),
    'value' => $item->menu_builder_args['id'] ?? '',
    'search' => true,
    'allowClear' => true
])

options là mảng chứa label và value.

Sau cùng vào ServiceProvider add CategoryMenuBuilder vừa tạo ở trên là xong:

    public function registerFrontendMenuBuilders()
    {
        \FrontendMenuBuilder::add(CategoryMenuBuilder::class);
    }