emberjs – 如何使用路由器基础设施标记活动菜单项

我正在尝试创build导航标签(取自Twitter Bootstrap ):

<ul class="nav nav-tabs"> <li class="active"><a href="#">Home</a></li> <li><a href="#">Profile</a></li> <li><a href="#">Messages</a></li> </ul> 

活动选项卡用class="active"标记。

在http://jsfiddle.net/schawaska/pfbva/有一个很好的静态导航栏和路由器/socketsfunction的例子,但我不明白如何创build一个dynamic的导航栏/菜单/标签视图。

据我所知,可以在每个菜单项中使用类绑定:

  classNameBindings: ['isActive:active'] 

但是在哪里切换isActive属性?

如果你使用Ember> = 1.11,那么下面的https://stackoverflow.com/a/14501021/65542是正确的答案。;


我会创build一个NavigationView ,请参阅http://jsfiddle.net/pangratz666/z8ssG/

把手

 <script type="text/x-handlebars" data-template-name="navigation"> <ul class="nav nav-tabs"> {{#view view.NavItemView item="home" }} <a {{action gotoHome}} >Home</a> {{/view}} {{#view view.NavItemView item="profiles" }} <a {{action gotoProfiles}} >Profiles</a> {{/view}} {{#view view.NavItemView item="messages" }} <a {{action gotoMessages}} >Messages</a> {{/view}} </ul> </script> 

JavaScript

 App.NavigationView = Em.View.extend({ templateName: 'navigation', selectedBinding: 'controller.selected', NavItemView: Ember.View.extend({ tagName: 'li', classNameBindings: 'isActive:active'.w(), isActive: function() { return this.get('item') === this.get('parentView.selected'); }.property('item', 'parentView.selected').cacheable() }) }); 

并且在你的路由的connectOutlets你必须通过router.set('navigationController.selected', 'home');设置当前的导航项router.set('navigationController.selected', 'home');


还要看看这个ember-bootstrap存储库,它包含了Ember.js中的Bootstrap的更多特性

Ember 1.11+:

 {{#link-to "dashboard" tagName="li"}} <a href="{{view.href}}">Dashboard</a> {{/link-to}} 

Ember <1.11(需要bind-attr ):

 {{#link-to "dashboard" tagName="li"}} <a {{bind-attr href="view.href"}}>Dashboard</a> {{/link-to}} 

以上build议中的一部分仍然适用于twitter bootstrap的情况。 你也可以尝试这样的事情

 {{#link-to 'dashboard' tagName='li'}} {{#link-to 'dashboard'}}Link Title{{/link-to}} {{/link-to}} 
  1. li tagName的link-to将活动类应用于li
  2. 内部link-to将是一个anchor元素,使您可以在右键单击时Open in New Tab

最近有一个Ember-cli插件可以做到这一点。 它被称为ember-cli-active-link-wrapper 。

安装: ember install ember-cli-active-link-wrapper

你可以像这样使用它:

 {{#active-link}} {{link-to "Index" "index"}} {{/active-link}} 

这导致:

 <li class='active'> <a href="/" class='active'>Index</a> </li> 

我知道这是旧的post,但这里是Ember 2.4.0的更新

为了创build链接,你可以写

 {{#link-to 'photoGallery'}} Great Hamster Photos {{/link-to}} 

要么

 {{link-to 'Great Hamster Photos' 'photoGallery'}} 

当前路线匹配链接的路线时,Ember会自动将类设置为活动状态(本例中为photoGallery )。

如果你想在其他路线上控制“主动”类,你可以通过设置current-when属性来实现。

 {{#link-to 'photoGallery' current-when='photoGallery photoPreview'}} Great Hamster Photos {{/link-to}} 

这个链接将在photoGalleryphotoPreview路线上都有active类。

https://github.com/emberjs/ember.js/blob/v2.4.0/packages/ember-routing-views/lib/components/link-to.js#L140

把手

 <ul class="nav"> <li>{{#linkTo "index"}}Index{{/linkTo}}</li> <li>{{#linkTo "about"}}About{{/linkTo}}</li> </ul> 

使用Javascript

 App.Router.map(function() { this.route("about"); }); 

它会根据路由自动添加活动类。 注意:它使用ember-1.0.0-pre.4.js进行testing

您也可以将isActive方法更改为如下所示:

 isActive: function() { return App.getPath('router.currentState.path') === "root.firms"; }.property("App.router.currentState"), 

要么

 isActive: function() { return this.get('controller.target.currentState.path') === "root.firms"; }.property("controller.target.currentState"), 

我看到这个问题是相当古老的,但如果你升级Ember.js RC3你可以使用tagName属性,如:

 {{#link-to messages tagName="li"}}Messages{{/link-to}} 

这里是API – http://emberjs.com/api/classes/Ember.LinkView.html

不确定这是非常dynamic的,但尝试看到解决schemehttp://codebrief.com/2012/07/anatomy-of-an-ember-dot-js-app-part-i-redux-routing-and-outlets/主要想法是检查你的应用程序的状态

JavaScript的:

 function stateFlag(name) { return Ember.computed(function() { var state = App.router.currentState; while(state) { if(state.name === name) return true; state = state.get('parentState'); } return false; }).property('App.router.currentState'); } ApplicationController: Ember.Controller.extend({ isHome: stateFlag('home'), isSections: stateFlag('sections'), isItems: stateFlag('items') }) 

把手:

 <li class="home" {{bindAttr class="isHome:active"}}> </li> <li class="sections" {{bindAttr class="isSections:active"}}> </li> <li class="items" {{bindAttr class="isItems:active"}}> </li> 

更新: pangratz的解决scheme看起来更漂亮

这是一个完整的工作解决scheme:

视图:

 App.NavView = Ember.View.extend({ tagName: 'li', classNameBindings: ['active'], active: function() { return this.get('childViews.firstObject.active'); }.property() }); 

模板:

 <ul> {{#each item in controller}} {{#view App.NavView}} {{#linkTo "item" item tagName="li"}} <a {{bindAttr href="view.href"}}> {{ item.name }} </a> {{/linkTo}} {{/view}} {{/each}} </ul> 

迟早想要改变你的状态的命名,或者你必须通过代码和视图以及添加一个函数transitionTo每个路线似乎不希望。 我的方法是更加程序化和模块化的:

 # Parent View-Tamplate, holding the navbar DOM elements App.NavView = Ember.View.extend( controller: App.NavArrayController templateName: "ember-nav" ) # We push NavItems into this array App.NavArrayController = Ember.ArrayController.create( content: Ember.A([]) ) # NavItem has two settable properties and # an programmatic active state depending on the router App.NavItem = Ember.Object.extend( title: '' goto: null # <=this is the name of the state we want to go to! active: (-> if App.router.currentState.name == @.get "goto" true else false ).property('App.router.currentState.name').cacheable() ) # the actual NavElement which gets the class="active" if the # property "active" is true, plus a on-click binding to # make the Router transition to this state App.NavItemView = Ember.View.extend( tagName: "li" classNameBindings: ["active"] click: -> App.router.transitionTo(@get('goto')) false ) 

nav-view.hbs(对于twitter-bootstrap风格的导航)

 <div class="nav-collapse collapse"> <ul class="nav"> {{#each App.NavArrayController}} {{#view App.NavItemView classBinding="active" gotoBinding="goto"}} <a href="#" {{bindAttr data-goto="goto"}}> {{title}}</a> {{/view}} {{/each}} </ul> </div> 

这样,我就可以在路由器中创build和处理我的路由,并且保持导航定义并行:

 # put this somewhere close to the Router App.NavArrayController.pushObjects( [ App.NavItem.create( title: 'Home' goto: 'home' ), App.NavItem.create( title: 'Chat' goto: 'chat' ), App.NavItem.create( title: 'Test' goto: 'test' ) ] ) 

baijum上面的答案大部分是正确的,但是在最新版本的Ember中,“bind-attr”已经被弃用了。 这是写它的新方法:

 {{#link-to "dashboard" tagName="li"}} <a href="{{view.href}}">Dashboard</a> {{/link-to}} 

正如你所看到的,它更简单,像魔术般的作品。

从v0.8.0开始, ember-bootstrap支持导航,包括正确处理活动状态。 而且,没有任何链接到/ tagNametypes的黑客:

 {{#bs-nav type="pills"}} {{#bs-nav-item}} {{#link-to "foo"}}Foo{{/link-to}} {{/bs-nav-item}} {{#bs-nav-item}} {{#link-to "bar"}}Bar{{/link-to}} {{/bs-nav-item}} {{/bs-nav}} 

http://kaliber5.github.io/ember-bootstrap/api/classes/Components.Nav.html

这里提出的很多解决scheme都不适用于最近的Ember版本(例如视图被弃用)。 此外,仅使用link-to帮助程序不会解决问题,因为引导程序期望active类在<li>而不是<a>

所以我会试着总结一下实际上现在工作的解决scheme:

使用ember-cli-active-link-wrapper

插件为这个特殊用例提供了一个组件:

 <ul class="nav nav-tabs"> {{#active-link}} {{#link-to "foo"}}Foo{{/link-to}} {{/active-link}} {{#active-link}} {{#link-to "bar"}}Bar{{/link-to}} {{/active-link}} </ul> 

采取从https://stackoverflow.com/a/29939821/5556104

使用ember-bootstrap

ember-bootstrap提供了许多将引导程序function集成到您的应用程序中的组件,其中包括nav组件:

 {{#bs-nav type="tabs"}} {{#bs-nav-item}} {{#link-to "foo"}}Foo{{/link-to}} {{/bs-nav-item}} {{#bs-nav-item}} {{#link-to "bar"}}Bar{{/link-to}} {{/bs-nav-item}} {{/bs-nav}} 

采取从https://stackoverflow.com/a/38279975/5556104

链接到哈克

有点hacky,但应该没有任何额外的插件工作:

 <ul class="nav nav-tabs"> {{#link-to "foo" tagName="li"}} {{#link-to "foo"}}Foo{{/link-to}} {{/link-to}} {{#link-to "bar" tagName="li"}} {{#link-to "bar"}}Bar{{/link-to}} {{/link-to}} </ul> 

采取从https://stackoverflow.com/a/23966652/5556104

与其他人一样,使用{{#link-to}}链接到现有route ,当该路由为当前URL时, {{#link-to}}将自动为其CSS类添加active

参见Ember issue 4387

Interesting Posts