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}}
- 与
li
tagName的link-to
将活动类应用于li - 内部
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}}
这个链接将在photoGallery
和photoPreview
路线上都有active
类。
把手
<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}}
不确定这是非常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>
与其他人一样,使用{{#link-to}}
链接到现有route
,当该路由为当前URL时, {{#link-to}}
将自动为其CSS类添加active
。
参见Ember issue 4387