I'd like to know how is it possible with vue.js to have a router with dynamic routes, instead of static ones, to render a menu based on the October Static Menu items and Pages ?
Thanks for help.
In October backend, I used regular MDBootstrap with the following partial to render a dynamic menu based on Static Pages and Menus :
<!-- Navbar Logo -->
<a class="navbar-brand" href="#">Navbar</a>
<!-- Collapse button -->
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<!-- Collapsible content -->
<div class="collapse navbar-collapse" id="navbarSupportedContent">
{% if staticMenu.menuItems %}
{% set items = staticMenu.menuItems %}
<!-- Links -->
<ul class="navbar-nav mr-auto">
{% for item in items %}
<li class="nav-item {{ item.isActive or item.isChildActive ? 'active' : '' }}
{{ item.items ? 'dropdown btn-group' : '' }}"
>
<a class="nav-link {% if item.items %}dropdown-toggle {% endif %}"
{% if item.items %} id="dropdownMenu{{ item.title|replace({' ':'-'}) }}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"{% endif %}
href="{{ item.url }}"
>
{{ item.title }}
{% if item.items %}<span class="sr-only">(current)</span>{% endif %}
</a>
{% if item.items %} <!-- Sous-menu -->
<div class="dropdown-menu dropdown-primary"
aria-labelledby="dropdownMenu{{ item.title|replace({' ':'-'}) }}">
{% for child in item.items %}
<a class="dropdown-item" href="{{ child.url }}">{{ child.title }}</a>
{% endfor %}
</div>
{% endif %}
</li>
{% endfor %}
{% endif %}
</ul>
<!-- Links -->
</div>
<!-- Collapsible content -->
<!-- Search form -->
<form class="form-inline">
<input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
</form>
<ul class="navbar-nav ml-auto nav-flex-icons">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink-333" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<i class="fas fa-user"></i>
</a>
<div class="dropdown-menu dropdown-menu-right dropdown-primary"
aria-labelledby="navbarDropdownMenuLink-333">
<a class="dropdown-item {{ this.page.baseFileName == 'login' ? 'active' : '' }}" href="{{ 'login'|page }}">
{% if not user %}
Login
{% else %}
My profile
{% endif %}
</a>
{% if user %}
<a class="dropdown-item" data-request="onLogout" data-request-data="redirect: '/logout'">Sign out</a>
{% endif %}
</a>
</div>
</li>
</ul>
</nav>
<!--/.Navbar-->
Items are properly rendered and modified if I change backend items.
Now I'd like to switch my frontend to a Vue.js app with MDB Vue.
In samples routes are always statics and in nice Watch+Learn Rentacar app also (https://watch-learn.com/creating-rent-car-app-vue-and-october/creating-rentacar-app-with-vue-and-october-homepage-ui)
I made a menu component with the following samples (https://mdbootstrap.com/docs/vue/navigation/navbar). Now that it is rendered, I'm wondering how in my vue component I could parse my backend items like in Twig ???
The menu component source (static) is :
<template>
<div>
<!--Navbar-->
<mdb-navbar dark color="primary" name="Your Logo" href="#">
<mdb-navbar-toggler>
<mdb-navbar-nav>
<mdb-nav-item to="/navigation/navigation-v1">Version 1</mdb-nav-item>
<mdb-nav-item to="/navigation/navigation-v2" active>Version 2</mdb-nav-item>
<mdb-nav-item to="/navigation/navigation-v3">Version 3</mdb-nav-item>
<mdb-nav-item to="/navigation/navigation-v4">Version 4</mdb-nav-item>
<!-- mdbDropdown -->
<mdb-dropdown tag="li" class="nav-item">
<mdb-dropdown-toggle slot="toggle" tag="a" navLink color="primary" waves-fixed>Dropdown</mdb-dropdown-toggle>
<mdb-dropdown-menu>
<mdb-dropdown-item>Action</mdb-dropdown-item>
<mdb-dropdown-item>Another action</mdb-dropdown-item>
<mdb-dropdown-item>Something else here</mdb-dropdown-item>
</mdb-dropdown-menu>
</mdb-dropdown>
</mdb-navbar-nav>
<!-- Search form -->
<form>
<mdb-input type="text" class="text-white" placeholder="Search" aria-label="Search" label navInput waves waves-fixed/>
</form>
</mdb-navbar-toggler>
</mdb-navbar>
<!--/.Navbar-->
</div>
</template>
<script>
import { mdbNavbar, mdbNavItem, mdbNavbarNav, mdbNavbarToggler, mdbDropdown, mdbDropdownItem, mdbDropdownMenu, mdbDropdownToggle, mdbInput } from 'mdbvue';
export default {
name: 'NavigationPage',
components: {
mdbNavbar,
mdbNavItem,
mdbNavbarNav,
mdbNavbarToggler,
mdbDropdown,
mdbDropdownItem,
mdbDropdownMenu,
mdbDropdownToggle,
mdbInput
},
mounted() {
document.getElementById("main-navbar").style.height = '60px';
},
beforeDestroy() {
document.getElementById("main-navbar").style.height = null;
}
};
</script>
Thanks for clues !
Well, I now made some progress to the solution ! In my Vue.js app, I would like to get JSON data with the menu levels. Based on this post (How to get static page dropdown in OctoberCMS with get page tree?) in my October plugin, I'm able to create a route which sends the data to Vue.js.
But when I do :
$theme = \Cms\Classes\Theme::getEditTheme();
$pageList = new \RainLab\Pages\Classes\PageList($theme);
$treePageList = $pageList->getPageTree(true);
return $treePageList;
I get a structure with too much details. How could I simplify it to have only a JSON data with the title and the url of my multilevel menu ? I would like to obtain something like :
"Sub pages" "sub-pages" +
"Child One" "child-1"
"Child Two" "child-2"
"Child Three" "child-3"
"Child Four" "child-4" +
"Sub Child" "sub-child"
"Forms" "forms" +
"Form Contact" "form-contact"
"test" "test"
Thanks for help !