How to create a dropdown navigation menu in aurelia

Hi everybody. I am trying to create a navigational dropdown menu in aurelia but so far no luck. I tried it wit adding a setting to the route and when that setting was true a drop down was being generated. This is sort of working but the downside of this is that I’m losing control over the order of the menu. Because it first loops over the items without the setting. And next it loops over the items with the setting. And offcourse in reallity I want to use them both together.

Is somebody aware of a best practice of creating a dropdown menu of does somebody have the golden tip?! I’m all ears :grin:.

Thanks!

1 Like

@NvdGoorbergh I never had issues with order but I haven’t worked through setting the activation status. Part of this would depend on what your menu looks like, I used standard Bootstrap 4. What I did was create a dummy item for the main heading and then when I hit that item I would output its children. Here is how I configured the map:

{
route: “settings”,
name: “settings”,
settings: { icon: “fa fa-cogs”, dropdown: “settings” },
moduleId: “#”,
nav: true,
title: “Settings”
}, {
route: “plant-settings”,
name: “plantsettings”,
settings: { dropdown: “settings” },
moduleId: “…/settings/plantSettings”,
nav: true,
title: “Plant”
}…

Then that was rendered in a control like this:

<template>
<require from="./navmenu.scss"></require>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
    <div class="navbar-brand">
        <a href="#/home"><img class="img-responsive" src="logoh.png" width="257" height="49"></a>
    </div>
    <div class="navbar-collapse collapse" id="navbarNav">
        <ul class="navbar-nav align-items-end">
            <template repeat.for="row of router.navigation">
                <li if.bind="!row.settings.dropdown" class="nav-item ${row.isActive ? 'active' : ''}">
                    <a href.bind="row.href" class="nav-link">
                        <i class="${row.settings.icon}"></i> ${row.title}
                    </a>
                </li>
                <li if.bind="row.settings.dropdown === row.config.route" class="nav-item dropdown ${row.isActive ? 'active' : ''}">
                    <a href.bind="row.href" class="nav-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        <i class="${row.settings.icon}"></i> ${row.title}
                    </a>
                    <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                        <template repeat.for="sub of router.navigation">
                            <a if.bind="sub.settings.dropdown !== sub.config.route && row.config.route === sub.settings.dropdown" href.bind="sub.href" class="dropdown-item">
                                <i class="${sub.settings.icon}"></i> ${sub.title}
                            </a>
                        </template>
                    </div>
                </li>
            </template>
        </ul>
    </div>
</nav>

Maybe this gives you some ideas?

2 Likes

Thanks. Will try this tonight!

it looks like what I had with some small changes (which could make a big difference!).
I had 2 repeat for’s which, now that I take a better look at it, will make it so that first all the not dropdown items are placed and then the dropdown items are placed.

Thanks, will let you know if that solves the issue!

1 Like

hmm… im getting there but this solution breaks the navigation inside de dropdown.
SyntaxError: expected expression, got ‘<’
TypeError: target is undefined

I think it has something to do with the module id being #.

1 Like

Fixed!!
It was indeed with the setting dropdown.
{
route: ‘over ons’,
name: ‘over ons’,
settings: { dropdown: ‘over ons’ },
moduleId: ‘./overons’,
nav: true,
title: ‘Over ons’
}, {
route: ‘organisatie’,
name: ‘organisatie’,
settings: { dropdown: ‘over ons’ },
moduleId: ‘./organisatie’,
nav: true,
title: ‘Organisatie’
}, {

then in the template I did:

<ul class="navbar-nav align-items-end">
        <template repeat.for="row of router.navigation">
            <li if.bind="!row.settings.dropdown" class="nav-item ${row.isActive ? 'active' : ''}">
                <a href.bind="row.href" class="nav-link">
                    <i class="${row.settings.icon}"></i> ${row.title}
                </a>
            </li>
            <li if.bind="row.settings.dropdown === row.config.route" class="nav-item dropdown ${row.isActive ? 'active' : ''}">
                <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                    <i class="${row.settings.icon}"></i> ${row.title}
                </a>
                <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                    <template repeat.for="sub of router.navigation">
                        <a if.bind="sub.settings.dropdown !== sub.config.route && row.config.route === sub.settings.dropdown" href.bind="sub.href" class="dropdown-item">
                            <i class="${sub.settings.icon}"></i> ${sub.title}
                        </a>
                    </template>
                </div>
            </li>
        </template>
    </ul>

which works! next challenge. getting the search input update the main page

1 Like