# Storing/Retrieving Navigation Menus/Route in Database

**URL:** <https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071>\
**Category:** Help Requests\
**Created:** [April 12, 2018, 7:54am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071 "2018-04-12T07:54:15Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![lvparkington](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/lvparkington/32/736_2.png) [@lvparkington](https://discourse.aurelia.io/u/lvparkington)\
**Post date:** [April 12, 2018, 7:54am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/1 "2018-04-12T07:54:15Z")

</div>

We are trying to create a configurable hierarchical menu navigation for Aurelia using information stored in a database. Using as starting point the Microsoft Net Core SPA templates and generating the values from a controller. These options would not be known until run time as the database may be updated with new routes as needs to be dynamic. After compiling and running, the following error is logged when selecting a menu item. Are we trying to do something that is not allowed? Would there be a workaround?

“ERROR [app-router] Error: Unable to find module with ID: app/components/counter/counter”

We’ve not been able to include screenshots or a working VS 2017 project but can email one if any help.  
[app.ts]  
import { Aurelia, PLATFORM } from ‘aurelia-framework’;  
import { Router, RouterConfiguration } from ‘aurelia-router’;  
import { HttpClient } from ‘aurelia-fetch-client’;  
import { inject } from ‘aurelia-framework’;

@inject(HttpClient)  
export class App {  
public navroutes: NavigationRoute[];  
constructor(http: HttpClient) {  
http.fetch(‘api/SampleData/DbRoutes’)  
.then(result =\> result.json() as Promise\<NavigationRoute[]\>)  
.then(data =\> {  
this.navroutes = data;  
// Add each route (including sub route(s) here  
for (var i = 0; i \< data.length; i++) {  
var navroute: NavigationRoute = data[i];

```
                this.router.addRoute({
                    route: navroute.route,
                    name: navroute.name,
                    settings: { icon: navroute.icon },
                    moduleId: PLATFORM.moduleName(navroute.moduleId.toString()), // does not work (read name of module from database) - webpack can't resolve it - workaround add in constructor   
                    //moduleId: PLATFORM.moduleName('../scheduler/scheduler'), // this works (typed name of module) - webpack can resolve it
                    nav: navroute.nav,
                    title: navroute.title
                })
                this.router.refreshNavigation();
            }
        });

```

router: Router  
configureRouter(config: RouterConfiguration, router: Router) {  
config.title = ‘Demo’;

```
    config.map([{
        route: ['', 'home'],
        name: 'home',
        settings: { icon: 'home' },
        moduleId: PLATFORM.moduleName('../home/home'),
        nav: true,
        title: 'Home' // The default home
    }]);

```

this.router = router  
}  
}

class NavigationRoute {  
id: number;  
parentId: any;  
route: string;  
name: string;  
icon: string;  
moduleId: string;  
nav: boolean;  
title: string;  
}  
…

---

<div class="post-metadata">

**Author:** ![MaximBalaganskiy](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/maximbalaganskiy/32/831_2.png) [@MaximBalaganskiy](https://discourse.aurelia.io/u/MaximBalaganskiy)\
**Post date:** [April 12, 2018, 11:52pm UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/2 "2018-04-12T23:52:25Z")

</div>

You cannot do `PLATFORM.moduleName(navroute.moduleId.toString())` - this string is analysed at bundle time, not runtime. You will have to either make `PLATFORM.moduleName` calls for each module or use `GlobalDependenciesPlugin` (or `AureliaPlugin` with `includeAll` flag)

---

<div class="post-metadata">

**Author:** ![lvparkington](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/lvparkington/32/736_2.png) [@lvparkington](https://discourse.aurelia.io/u/lvparkington)\
**Post date:** [April 13, 2018, 7:41am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/3 "2018-04-13T07:41:16Z")

</div>

Thanks for your help. I checked the calls work correctly at run time as long as the reference is defined useing the explicit string before hand. So needs to be recompiled every time the contents of database call change. See snippet below. Now to get sub routes working 🙂 Treating Routes as Modules does not seem right to me?  
…  
constructor(http: HttpClient) {  
// Declare all routes returned from the database otherwise routing will not work. This needs to be recompiled whenever these change  
PLATFORM.moduleName(’…/scheduler/scheduler’); // workaround  
PLATFORM.moduleName(’…/newcustomer/newcustomer’); // workaround  
PLATFORM.moduleName(’…/searchcustomers/searchcustomers’); // workaround  
[//PLATFORM.moduleName](https://PLATFORM.moduleName)(’…/newquote/newquote’); // workaround  
[//PLATFORM.moduleName](https://PLATFORM.moduleName)(’…/searchquotes/searchquotes’); // workaround  
// Read the navigation from database  
http.fetch(‘api/SampleData/DbRoutes’)  
.then(result =\> result.json() as Promise\<NavigationRoute[]\>)  
.then(data =\> {  
this.navroutes = data;  
var subroutes: NavigationRoute[] = [];  
// Add each route (including sub route(s) here  
for (var i = 0; i \< data.length; i++) {  
var navroute: NavigationRoute = data[i];  
if (navroute.parentId == null) {  
this.router.addRoute({  
route: navroute.route,  
name: navroute.name,  
settings: { icon: navroute.icon },  
moduleId: PLATFORM.moduleName(navroute.moduleId.toString()), // Note: this only works database routes have been explicitly compiled previously  
nav: navroute.nav,  
title: navroute.title  
})  
this.router.refreshNavigation();  
}  
}  
});  
}

---

<div class="post-metadata">

**Author:** ![MaximBalaganskiy](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/maximbalaganskiy/32/831_2.png) [@MaximBalaganskiy](https://discourse.aurelia.io/u/MaximBalaganskiy)\
**Post date:** [April 13, 2018, 8:39am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/4 "2018-04-13T08:39:25Z")

</div>

The route itself is not a module, the module gets rendered as a navigation result.

It’s not really a workaround, but rather a documented way in webpack. The subroutes are defined in respective modules via configureRouter function.

---

<div class="post-metadata">

**Author:** ![MaximBalaganskiy](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/maximbalaganskiy/32/831_2.png) [@MaximBalaganskiy](https://discourse.aurelia.io/u/MaximBalaganskiy)\
**Post date:** [April 13, 2018, 8:40am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/5 "2018-04-13T08:40:40Z")

</div>

If you need truly dynamic routing you’ll have to use cli with require or jspm - they are capable of loading modules outside bundles

---

<div class="post-metadata">

**Author:** ![lvparkington](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/lvparkington/32/736_2.png) [@lvparkington](https://discourse.aurelia.io/u/lvparkington)\
**Post date:** [April 13, 2018, 9:58am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/6 "2018-04-13T09:58:59Z")

</div>

I’m having trouble getting these plugins to work: AureliaPlugin will work with includeAll: false but not includeAll: true. I can’t get the GlobalDependenciesPlugin to work at all. Could you point me in the right direction to configure an example so I can put a few PLATFORM.moduleName s in a file to get this working? The following webpack.confiog.js just blows up  
…  
plugins: [  
new webpack.DefinePlugin({ IS\_DEV\_BUILD: JSON.stringify(isDevBuild) }),  
new webpack.DllReferencePlugin({  
context: \_\_dirname,  
manifest: require(’./wwwroot/dist/vendor-manifest.json’)  
}),  
new GlobalDependenciesPlugin(),  
new AureliaPlugin({ aureliaApp: “boot”, includeAll: false })  
].concat(isDevBuild ? [  
new webpack.SourceMapDevToolPlugin({  
filename: ‘[file].map’, // Remove this line if you prefer inline source maps  
moduleFilenameTemplate: path.relative(bundleOutputDir, ‘[resourcePath]’) // Point sourcemap entries to the original file locations on disk  
})  
] : [  
new webpack.optimize.UglifyJsPlugin()  
])  
}];

---

<div class="post-metadata">

**Author:** ![MaximBalaganskiy](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/maximbalaganskiy/32/831_2.png) [@MaximBalaganskiy](https://discourse.aurelia.io/u/MaximBalaganskiy)\
**Post date:** [April 13, 2018, 10:28am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/7 "2018-04-13T10:28:41Z")

</div>

It’s not really a flag, you need to set it to a path, relative to config location

---

<div class="post-metadata">

**Author:** ![lvparkington](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/lvparkington/32/736_2.png) [@lvparkington](https://discourse.aurelia.io/u/lvparkington)\
**Post date:** [April 13, 2018, 10:47am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/8 "2018-04-13T10:47:58Z")

</div>

I’ve used the following configuration but keep getting the TypeScript error message ‘Unable to find module with ID: boot’. It loads but does not compile all the files if includeAll is set to false

new AureliaPlugin({ aureliaApp: ‘boot’, includeAll: ‘…/…/app/components/app’ })

---

<div class="post-metadata">

**Author:** ![MaximBalaganskiy](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/maximbalaganskiy/32/831_2.png) [@MaximBalaganskiy](https://discourse.aurelia.io/u/MaximBalaganskiy)\
**Post date:** [April 13, 2018, 10:57am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/9 "2018-04-13T10:57:02Z")

</div>

First of all, that relative path doesn’t look right, should be something like “src/components”…

Secondly, is there “boot” file?

Have a look at this example for webpack 4

> <https://github.com/aurelia-ui-toolkits/demo-materialize/blob/master/webpack.config.js>

---

<div class="post-metadata">

**Author:** ![lvparkington](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/lvparkington/32/736_2.png) [@lvparkington](https://discourse.aurelia.io/u/lvparkington)\
**Post date:** [April 13, 2018, 11:05am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/10 "2018-04-13T11:05:16Z")

</div>

This is Net Core project produced using Microsoft SPA templates ([https://blogs.msdn.microsoft.com/webdev/2017/02/14/building-single-page-applications-on-asp-net-core-with-javascriptservices/](https://blogs.msdn.microsoft.com/webdev/2017/02/14/building-single-page-applications-on-asp-net-core-with-javascriptservices/)) and there is no ‘src’ directory present. There is a boot.ts file in ClientApp directory hence the directory should be resolvable (ClientApp/app/components/app contains the app.html and app.ts files). The application will only load at all if includeAll is either set to false or not present. It looks like there may be more hardcoding than expected in the JavaScript/TypeScript so like looking for a needle in a haystack. (VS 2017 project has 12,530 files!)

---

<div class="post-metadata">

**Author:** ![MaximBalaganskiy](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/maximbalaganskiy/32/831_2.png) [@MaximBalaganskiy](https://discourse.aurelia.io/u/MaximBalaganskiy)\
**Post date:** [April 13, 2018, 11:10am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/11 "2018-04-13T11:10:14Z")

</div>

Then `includeAll: "ClientApp/app/components"`

---

<div class="post-metadata">

**Author:** ![lvparkington](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/lvparkington/32/736_2.png) [@lvparkington](https://discourse.aurelia.io/u/lvparkington)\
**Post date:** [April 13, 2018, 11:31am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/12 "2018-04-13T11:31:27Z")

</div>

Afraid still getting the same error. There could be versioning problems in the packages due to Node and NPM versions since expected behaviour is not being observed here. In desperation I have created a routes.ts file in the app folder and added and import ‘./routes’; which does work (the constructor runs but cannot be stepped through) without the plugin needing configuration. This routes.ts file contains the following and Webpack compiles the references.

import { Aurelia, PLATFORM } from ‘aurelia-framework’;

export class DbRoutes {  
constructor(http: HttpClient) {  
PLATFORM.moduleName(’…/scheduler/scheduler’);  
PLATFORM.moduleName(’…/newcustomer/newcustomer’);  
PLATFORM.moduleName(’…/searchcustomers/searchcustomers’);  
[//PLATFORM.moduleName](https://PLATFORM.moduleName)(’…/newquote/newquote’);  
[//PLATFORM.moduleName](https://PLATFORM.moduleName)(’…/searchquotes/searchquotes’);  
}

Would it be helpful if I sent you a zipped up project file since the Microsoft SPA template may be causing issues (or something else)

---

<div class="post-metadata">

**Author:** ![MaximBalaganskiy](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/maximbalaganskiy/32/831_2.png) [@MaximBalaganskiy](https://discourse.aurelia.io/u/MaximBalaganskiy)\
**Post date:** [April 13, 2018, 11:36am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/13 "2018-04-13T11:36:42Z")

</div>

How about a fresh dotnet project on GitHub to which I can suggest a pr?

---

<div class="post-metadata">

**Author:** ![lvparkington](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/lvparkington/32/736_2.png) [@lvparkington](https://discourse.aurelia.io/u/lvparkington)\
**Post date:** [April 13, 2018, 11:57am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/14 "2018-04-13T11:57:56Z")

</div>

Sounds good plan! Any particular repository?

---

<div class="post-metadata">

**Author:** ![MaximBalaganskiy](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/maximbalaganskiy/32/831_2.png) [@MaximBalaganskiy](https://discourse.aurelia.io/u/MaximBalaganskiy)\
**Post date:** [April 13, 2018, 12:18pm UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/15 "2018-04-13T12:18:40Z")

</div>

Nope, you can create a public one and post a link here.

---

<div class="post-metadata">

**Author:** ![lvparkington](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/lvparkington/32/736_2.png) [@lvparkington](https://discourse.aurelia.io/u/lvparkington)\
**Post date:** [April 16, 2018, 1:06pm UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/16 "2018-04-16T13:06:45Z")

</div>

I have now implemented a solution to this problem (simply adds a Scheduler navigation and page) at the repository [https://github.com/parkingtonl/pioneer](https://github.com/parkingtonl/pioneer).

 ![image](https://canada1.discourse-cdn.com/flex027/uploads/aurelia/original/1X/f5d87869d5aec3855f9211298252de7062001042.png)

If the database is not set up or configured correctly a dialog is displayed after the promises have completed

 ![image](https://canada1.discourse-cdn.com/flex027/uploads/aurelia/original/1X/fd875e11f440534da41ff70c10f1cfa2962e2b11.png)

---

<div class="post-metadata">

**Author:** ![MaximBalaganskiy](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/maximbalaganskiy/32/831_2.png) [@MaximBalaganskiy](https://discourse.aurelia.io/u/MaximBalaganskiy)\
**Post date:** [April 16, 2018, 1:55pm UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/17 "2018-04-16T13:55:08Z")

</div>

I’ve created a PR. Webpack builds and the modules are in the bundle.  
Mind you, the project is using old packages throughout - e.g. webpack 2.  
Also, splitting is not optimal - two config files are needed. It can be made simpler.  
If I get some time tomorrow, I’ll create a repo with the updated dotnet template.

---

<div class="post-metadata">

**Author:** ![lvparkington](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/lvparkington/32/736_2.png) [@lvparkington](https://discourse.aurelia.io/u/lvparkington)\
**Post date:** [April 16, 2018, 3:07pm UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/18 "2018-04-16T15:07:41Z")

</div>

Just wondering if there is an easy way to do hierarchical (nested) navigation menus? Not many working examples available. I’ve tried applying a subRoutes as property but only nests one level and seems uncooperative?

---

<div class="post-metadata">

**Author:** ![lvparkington](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/lvparkington/32/736_2.png) [@lvparkington](https://discourse.aurelia.io/u/lvparkington)\
**Post date:** [April 16, 2018, 3:34pm UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/19 "2018-04-16T15:34:08Z")

</div>

It has been noticed the builds for some NPM dependencies are very easily broken, for example, importing an NPM such as sweetalert using npm install sometimes remove up to a hundred packages and breaks the build. The only way to get it working again is to have a working copy of the node\_modules backed up at all times as webpack appears to bust itself. This is being developed for a commercial project so needs to be made much more robust when time permits.

---

<div class="post-metadata">

**Author:** ![MaximBalaganskiy](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/maximbalaganskiy/32/831_2.png) [@MaximBalaganskiy](https://discourse.aurelia.io/u/MaximBalaganskiy)\
**Post date:** [April 17, 2018, 12:18am UTC](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071/20 "2018-04-17T00:18:18Z")

</div>

AFAIK, there is no `subRoutes` field. I remember seeing an enhancement for the router to be able to get all the routes with children. Not sure it’s been implemented, may be @Alexander-Taran knows.

In the mean time, I register all the routes in the root view and provide an additional parameter - root menu name. Then your nav element can group routes by this parameter and display them in suitable fashion.

[Next page](https://discourse.aurelia.io/t/storing-retrieving-navigation-menus-route-in-database/1071.md?page=2)
