Aurelia: Easy way to create nested/multi level navigation menu

戏子无情 提交于 2020-01-03 19:07:08

问题


I need to create a multilevel navigation menu. The contents of the menu vary depending on the user. I plan on pulling the collection of navigation items that can contain an array of child items via a service that will return the data as JSON. Every example of navigation/routing I've seen uses static routes or single level menus. I have read a bit about child routing but that does not seem to be what I need. The only thing I can think of is to create a custom navigation element who's model will register the routes in a plain array using the data in the navigation items collection. I would then use this collection to render the HTML instead of using router as it contains the hierarchical information. Is there an easier way to do this. This is the first JS framework I have worked with so I'm trying to get up to speed.


回答1:


This is fairly easy, actually. You'll just add a property to the route's settings object. You can name it whatever you want. It'll have a collection of menu items for the sub menu. Just use that to build the sub-menu.

Here's an example: https://gist.run?id=beb5ba9155fdb2ccefcf78676879b1ca

app.html

<template>
  <ul>
    <li repeat.for="row of router.navigation" class="${row.isActive ? 'active' : ''}">
      <a href.bind="row.href">${row.title}</a>
      <ul>
        <li repeat.for="sub of row.settings.subRoutes">
          <a route-href="route.bind: row.config.name; params.bind: sub.params">${sub.name}</a>
        </li>
      </ul>
    </li>
  </ul>

  <div class="page-host">
    <router-view></router-view>
  </div>
</template>

app.js

import {activationStrategy} from 'aurelia-router';

export class App {
  configureRouter(config, router) {
    config.title = 'Aurelia';
    config.map([
      { 
        route: ['', 'one'], 
        name: 'one',      
        moduleId: 'one',      
        nav: true, 
        title: 'Page 1',
        activationStrategy: activationStrategy.invokeLifecycle,
        settings: {
          subRoutes: [
            {
              name: 'Sub-choice 1',
              params: {
                'foo': 'bar'
              }
            },
            {
              name: 'Sub-choice 2',
              params: {
                'foo': 'two'
              }
            }
          ]
        }
      },
      { route: 'two',         name: 'two',        moduleId: 'two',        nav: true, title: 'Page 2' }
    ]);

    this.router = router;
  } 
}

one.html

<template>
  Page One<br />
  Params:<br />
  <pre><code>${params}</code></pre>
</template>

one.js

export class One {
  activate(params) {
    this.params = JSON.stringify(params);
  }
}

The parameters you pass can be anything you like. For example, they could be the information on what route the should be activated on a child router on the route you're going to. You could call router.navigate... in the activate method of the page (one.js in the example below) to navigate to the correct route on the child router. You really can do whatever you want, since you can put any old thing you'd like on that settings object.




回答2:


I have solved similar problem in following way:

  1. I have simple navigation tree retrieved from the server
  2. Then I walk the tree and convert all the navigation items to the aurelia routes, actually flatten tree to array, so every route will have settings property like: {id: 2, parentId: 1, level: 1} at that moment
  3. Then I pass this flat array to config.map() and create a new tree object using items from router.navigation (remember: I saved id and parentId in settings) on router.ensureConfigured().then(_ => {createNavTree(router.navigation)})
  4. Use output from createNavTree(...) to render list items. (level is used just for some styling)
  5. So in general I create flat router.navigation array and use its items to create own tree structure to render the navigation

Also I listen for changes in router.currentInstruction to track menu collapsing when subitem is navigated using injected ObserverLocator.

`import {ObserverLocator} from 'aurelia-framework';`
...
this.routerCurrentInstructionSub = this.observerLocator
  .getObserver(router, 'currentInstruction')
  .subscribe((newValue, oldValue) => { ... });

Note that subscription should be released when not needed to avoid memory leaks this.routerCurrentInstructionSub.dispose();

The main benefit of this solution - is that you get full-featured routes, so you can render tree subitems as active while navigating.

Also it doesn't restrict using sub routers for sub items.



来源:https://stackoverflow.com/questions/41577897/aurelia-easy-way-to-create-nested-multi-level-navigation-menu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!