如何根据当前路由应用条件类属性?

时间:2017-03-12 10:15:44

标签: typescript aurelia aurelia-binding aurelia-router

我的应用程序中有一个导航组件,它有几个指向不同页面的链接,这些链接将通过路由访问。如果路由器当前位于链接所指的同一页面上,我想将导航项显示为“活动”。我尝试了几件事,直到我最终得到以下代码,根据当前路线动态设置CSS类:

模板:

<template>
  <div>
    <ul>
      <li class.bind="overviewClass"><a href="#/batch/overview">Overview</a></li>
      <li class.bind="completedJobsClass"><a href="#/batch/completed-jobs">Completed Jobs</a></li>
      <li class.bind="jobDefinitionsClass"><a href="#/batch/job-definitions">Job Definitions</a></li>
    </ul>
  </div>
</template>

视图模型:

import {inject} from 'aurelia-framework';
import {Router} from 'aurelia-router';

@inject(Router)
export class Navigation {
  constructor(private router: Router){
  }

  get overviewClass(){
    return this.isActive("overview") ? "active" : "";
  }

  get completedJobsClass(){
    return this.isActive("completed-jobs") ? "active" : "";
  }

  get jobDefinitionsClass(){
    return this.isActive("job-definitions") ? "active" : "";
  }

  isActive(routeName: string){
    if( this.router.currentInstruction != null && this.router.currentInstruction.config.name == routeName ){
      return true;
    }

    return false;
  }
}

此代码确实按预期工作。我的问题是我需要找到一个更具动态性的解决方案,因为此解决方案无法扩展。目前,我需要为每个导航项添加一个getter 。我需要实现。

我尝试使用函数而不是getter,但在我的所有情况下问题都是this.router.currentInstruction的值为null。

是否有一种有效的方法来实现带参数的函数,以便我可以从模板绑定它而无需为每个链接添加函数或getter?

非常感谢你的帮助。

2 个答案:

答案 0 :(得分:2)

您可以使用内置方式检查您所在的路线是否为活动路线。 Aurelia路由器已经为您提供此属性。如果您不希望将某些路由添加到UI,则可以使用路由定义中的nav属性并将其设置为false,并且不会将其添加到{{1数组。

就像这个例子一样:

路由器配置

route.navigation

您要在哪里显示菜单

 { route: 'users',            name: 'users',      moduleId: 'users/index',   nav: true },
  { route: 'users/:id/detail', name: 'userDetail', moduleId: 'users/detail' },

答案 1 :(得分:0)

我使用了自定义属性:

// is-active.js

import { Router } from 'aurelia-router';
import { EventAggregator } from 'aurelia-event-aggregator';
import { inject, customAttribute, DOM, bindable } from 'aurelia-framework';

const EVENT_NAME = 'router:navigation:success';

@inject(DOM.Element, Router, EventAggregator)
@customAttribute('is-active')
@bindable({ name: 'route' })
@bindable({ name: 'selector', defaultValue: 'is-active' })
export class IsActiveCustomAttribute {

    constructor(element, router, eventAggregator) {
        this.router = router;
        this.element = element;
        this.ea = eventAggregator;
    }

    attached() {
        this.subscriber = this.ea.subscribe(EVENT_NAME, this.handler.bind(this));
    }

    detached() {
        this.subscriber.dispose();
    }

    handler() {
        let config = this.router.currentInstruction.config;
        let currentRoute = config.name;
        let hasSelector = this.element.classList.contains(this.selector);
        let matchChildren = config.route.split('/', 1)[0] === this.route;

        if (this.route === currentRoute || matchChildren) {
            if (!hasSelector) {
                this.element.classList.add(this.selector);
            }
        } else if (hasSelector) {
            this.element.classList.remove(this.selector);
        }
    }
}

// html

<nav class="mdl-navigation mdl-layout--large-screen-only">
    <a class="mdl-navigation__link" 
        is-active="route: courses" 
        route-href="route: courses">Courses</a>

    <a class="mdl-navigation__link" 
        is-active="route: freebies" 
        route-href="route: freebies">Freebies</a>

    <a class="mdl-navigation__link" 
        is-active="route: blog" 
        route-href="route: blog">Blog</a>
</nav>