emberjs - how to mark active menu item using router infrastructure
Solution 1
If you're using Ember >= 1.11, then https://stackoverflow.com/a/14501021/65542 below is the correct answer.
I would create a NavigationView
, see http://jsfiddle.net/pangratz666/z8ssG/:
Handlebars:
<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()
})
});
And inside your route's connectOutlets
you have to set the current navigation item via router.set('navigationController.selected', 'home');
...
Also take a look at the ember-bootstrap repository, which wraps this and more features of Bootstrap inside Ember.js
Solution 2
Ember 1.11+:
{{#link-to "dashboard" tagName="li"}}
<a href="{{view.href}}">Dashboard</a>
{{/link-to}}
Ember < 1.11 (bind-attr
required):
{{#link-to "dashboard" tagName="li"}}
<a {{bind-attr href="view.href"}}>Dashboard</a>
{{/link-to}}
Solution 3
Some of the above suggestions are still valid for twitter bootstrap case. You can also try something like this
{{#link-to 'dashboard' tagName='li'}}
{{#link-to 'dashboard'}}Link Title{{/link-to}}
{{/link-to}}
- The
link-to
withli
tagName applies the active class to the li - The inner
link-to
would be aanchor
element which gives youOpen in New Tab
functionality when right-clicked
Solution 4
Recently an Ember-cli addon came available to just do this. It is called ember-cli-active-link-wrapper.
Install: ember install ember-cli-active-link-wrapper
You can use it like this:
{{#active-link}}
{{link-to "Index" "index"}}
{{/active-link}}
which results in:
<li class='active'>
<a href="/" class='active'>Index</a>
</li>
Solution 5
I know this is old post, but here are updates for Ember 2.4.0
For creating links you can write
{{#link-to 'photoGallery'}}
Great Hamster Photos
{{/link-to}}
or
{{link-to 'Great Hamster Photos' 'photoGallery'}}
Ember will automatically set class to active when current route matches link's route (in this example photoGallery
).
If you want to control 'active' class on other routes as well, you can do it by setting current-when
attribute.
{{#link-to 'photoGallery' current-when='photoGallery photoPreview'}}
Great Hamster Photos
{{/link-to}}
This link will have active
class on both photoGallery
and photoPreview
routes.
coxx
Updated on July 09, 2022Comments
-
coxx almost 2 years
I'm trying to create navigation tabs (taken from 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>
The active tab is marked with
class="active"
.There is great example of static navbar and Router/Outlet feature at http://jsfiddle.net/schawaska/pfbva/, but I can't understand how to create a dynamic navbar/menu/tab view.
As far as I understand, it is possible to use class bindings in each menu item:
classNameBindings: ['isActive:active']
But where is the right place to switch isActive attributes ?
-
Yehuda Katz over 11 yearscan you update your answer to reflect changes in the new router? Check out stackoverflow.com/questions/14328295/….
-
Yehuda Katz over 11 yearsThanks so much @pangratz. You're a rock star.
-
Lance over 11 yearswhat if you want the tabs to change without the url changing? (while also still using the router to get to the tabs, which are at say
/wizards/:wizard_id/edit
and there are 3 steps to edit in the wizard which you don't want to change the url.) -
jonnii about 11 yearsThis needs to be the accepted answer. I just spent 10 minutes trying to get a
bindAttr
on an <li> tag to reference the view.href by name until I found this and realized I had it all backwards. -
Terry about 11 years@jonnii Agree, I've posted a full solution below combining the two pieces.
-
Willem de Wit about 11 yearsThis is definitely the easiest way to do it
-
Willem de Wit about 11 yearsThe problem is that this approach doesn't work with a nested menu
-
Bastes about 11 yearsI guess with a nested menu, you'll need some specific component to handle it for you. Anyway this is the cleanest and easiest way to do it in the context of the original question.
-
bazzel about 11 yearsFWIW, I updated pangratz's example as illustrated with this jsfiddle
-
Zach Riggle about 11 yearsDefinitely the best answer I found out of the group.
-
pedalpete about 11 yearsThis works, the only issue I'm having is that it doesn't set the default on my root link. I render my index template to my 'Intro' controller, but this doesn't set the class on the link. Any idea how to do that?
-
roman almost 11 yearsThis is definately the most easiest way to do it! Should be the accepted answer.
-
Jagu over 10 yearsJust adding my support. A much better answer.
-
davidbuttar over 10 yearsHow exactly is the poor soul who comes across my code after I've inserted this oddity supposed to know that it will insert an 'active' class in the li? Very unclear.
-
Gabriel Grant over 10 yearsYou'll want to explicitly style your cursor to be a pointer when over the link element:
a {cursor: pointer;}
See marceldegraaf.net/2013/05/17/… -
chrmod about 10 yearsAFAIK this solution will not work anymore as
href
wont be generated for a nona
tags: discuss.emberjs.com/t/tagname-and-html-best-practices/4260/3 -
Simon about 9 years@bazzel: Unfortunately this is not working any more.
-
Kieran Huggins about 9 yearsThis is what we do, ideal for TWBS tabs
-
moger777 about 9 yearsThis sort of works but the href for <a> tag does not work so command + click won't open in new tabs
-
freeze almost 9 yearsThere should be better way that is not interresting, I have often to connect route logic to present logic. That is a bad way
-
Nuck about 8 yearsThis should really be the accepted answer. All the higher-upvoted ones are broken in modern Ember or otherwise unmaintainable.
-
Simon Ihmig almost 8 yearsThis should not be the accepted answer anymore, as this won`t work for any recent ember version. I tried the summarize the working solutions here: stackoverflow.com/a/38634312/5556104