Assigning 'active' class to selected list

2019-01-16 14:07发布

I have a list and I'd like to set one item as class="active" automatically. Given the following bootstrap code:

<ul class="nav">
<li {{bindAttr class="atIndex:active"}}>{{#linkTo "index"}}Index{{/linkTo}}</li>
<li {{bindAttr class="atAbout:active"}}>{{#linkTo "about"}}About{{/linkTo}}</li>
<li {{bindAttr class="atLogin:active"}}>{{#linkTo "login"}}Login{{/linkTo}}</li>
</ul>

atIndex, atAbout and atLogin reside in my ApplicationController.

To render as:

<ul class="nav">
<li class="active"><a...>Index{{/linkTo}}</li>
<li><a...>About<a></li>
<li><a...>Login<a></li>
</ul>

What's the best way to do this with Ember 1.0 pre4? I'd rather not add special code to every view or controller.

PS - atIndex: true works, but atIndex: function() {return true; }.property().volatile() does not. Which makes me think I'm doing something wrong.

Thank you!

标签: ember.js
12条回答
地球回转人心会变
2楼-- · 2019-01-16 14:47

Just nest the {{link-to}} with a tagName on the outer one. I'm doing this on EmberJS 2.0.

{{#link-to "admin.websocket" tagName="li"}}
    {{#link-to "admin.websocket"}}WebSocket{{/link-to}}
{{/link-to}}
查看更多
一纸荒年 Trace。
3楼-- · 2019-01-16 14:47

I solved a similar problem by creating a view for each item and using classNameBindings (I have to say that i don't have a HTML list, i.e.<a>...</a> in my app, just list of <div>).

Here is the way it works for me:

In tasklist.handlebars i iterate over my custom view

  {{#each tasks}}
    {{view App.TaskListItemView contentBinding="this"....}}
  {{/each}}

Ember will insert a view (i. e. <div>) for each item.

The view class for each item is defined in task_list_item_view.js as

App.TaskListItemView = Ember.View.extend({

  controller: null,
  classNameBindings: ['isSelected', 'isClosed'],

  isClosed: function() {
      var content = this.get('content');
      return content && !content.isOpen(new Date);
  }.property('controller.content.@each'),

  isSelected: function() {
      return (this.get('controller').isSelectedTask(this.get('content')));
  }.property('controller.taskSelection.@each'),

  ....
});

Finally the template for the view just renders my link in tasklistitem.handlebars

<a {{action "selectTask" view.content target="view"}} rel="tooltip"
         {{bindAttr title="view.content.comment"}} class="taskListLink">
  ....
</a>

AFAIK you have to specify the source data in the property() call to let ember know when to (re-) evaluate the property.

Hope that helps

查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-01-16 14:49

I went with:

 Ember.LinkView.reopen({
didInsertElement:function(){

    if(this.$().hasClass('active')){

        this.$().parent().addClass('active');

    }
}

});

I didn't want to use the accepted answer as I wanted to keep my li elements as plain old html. There might be a better way to check the active state but I couldn't get access to the right property.

查看更多
够拽才男人
5楼-- · 2019-01-16 14:50

A lot of these answers are outdated. Here is a much cleaner (and DRY) version for Bootstrap and Ember 2.x:

{{#link-to "index" tagName="li" as |link|}}
  <a href="#" class="{{if link.active 'active'}}">Index Page</a>
{{/link-to}}
查看更多
聊天终结者
6楼-- · 2019-01-16 14:54
{{#link-to "dashboard" tagName="li" href=false}}
  <a {{bind-attr href="view.href"}}>
    Dashboard
  </a>
{{/link-to}}
查看更多
Juvenile、少年°
7楼-- · 2019-01-16 14:55

the active route's path is updated automatically in the ApplicationController via currentPath so I did something like that in my App... In ApplicationController added properties like so:

isProductsActive: function(){
  if ( this.get('currentPath') === 'products' ) return 'active';
  else return '';
}.property('currentPath')

and in my ApplicationView template:

<li {{bindAttr class="isProductsActive"}}>
  {{#linkTo "products"}}Products{{/linkTo}}
</li>
查看更多
登录 后发表回答