根据索引,如何将Css类添加到Ember的{{#each}}循环中的项目? - Ember.js [英] How to add Css Class to item inside Ember's {{#each}} loop, according to index? - Ember.js

查看:75
本文介绍了根据索引,如何将Css类添加到Ember的{{#each}}循环中的项目? - Ember.js的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带侧边菜单的Ember应用程序。
html中的菜单项基于Ember的{{each}}循环。
当用户选择一个菜单项时,我想添加这个项目活动类。



如何在Ember的{{each}
根据控制器的条件



Html / Hbs:

 code>< UL> 
{{#each menuItem in sideMenuItems}}
< li {{bind-attr class =isActive:active-class}} {{action'selectMenuItem'_view.contentIndex}}>
{{menuItem.text}}
< / li>
{{/ each}}
< / ul>

控制器:

 code> Ember.ObjectController.extend({
selectedMenuInde​​x:0,
isActive:function(){
return(this.get('selectedMenuInde​​x')==??? ;
} .property('???'),

actions:{
selectMenuItem:function(itemIndex){
this.set('selectedMenuInde​​x' itemIndex);
}
}
})


解决方案


当用户选择菜单项时,我想添加这个项目活动类。




由于您使用的是Ember 1.5,我将首先向您展示一些旧版本的方法。



最简单的方法是添加标题 isActive 到项目本身,并将其用作css类的条件。您可以为 selectMenuItem 操作中的点击项目设置标志为 true 。如果您的逻辑仅允许单个项目一次处于活动状态,则还必须将任何当前活动的项目的 isActive 标志重置为 false

  {{#sideMenuItems中的每个菜单项}} 
< li {{bind-attr class =menuItem。 isActive:active-class}} {{action'selectMenuItem'_view.contentIndex}}>
{{menuItem.text}}
< / li>
{{/ each}}

控制器:

  Ember.ObjectController.extend({

sideMenuItems:// ...您的数组项,每个都包含一个isActive标志

actions:{
selectMenuItem:function(itemIndex){
var items = this.get('sideMenuItems');
items.forEach(function(item,idx){ //通过项目
if(idx === itemIndex){//找到点击的项目并将其设置为活动
Ember.set(item,'isActive',true);
} else {//重置所有其他项目
Ember.set(item,'isActive',false);
}
});
}
}
})

更有效的方法是将当前活动的项目作为单独的变量,这将消除需要迭代 sideMenuItems 数组两次:



Con troller:

  Ember.ObjectController.extend({

sideMenuItems:// ...你的数组的项目,每个都包含一个isActive标志
activeMenuItem:null,

actions:{
selectMenuItem:function(itemIndex){
var items = this.get(' sideMenuItems');
var currActive = this.get('activeMenuItem');
var nextActive = items.objectAt(itemIndex);

//如果有一个当前活动的项目,停用它
if(currActive){
Ember.set(currActive,'isActive',false);
}

//如果用户点击当前活动的项目,我们只需重置所选项目
//否则我们更新点击的项目的isActive标志
if(currActive === nextActive){
nextActive = null;
} else {
Ember.set(nextActive,'isActive',true);
}

//将点击的项目设置为当前活动的菜单项
this.set('activeMenuItem',nextActive);
}
})






另一种方法是创建一个自定义组件菜单项,它呈现您的 li 项目带有/不带类取决于活动索引。

  Ember.Component.extend({

//传入
activeIndex:-1,
index:-1,
selectMenuItemAction:'',

// local
tagName:'li',
classNameBindings:['activeClass'],

activeClass:function(){
var idx = this.get('index');
var activeIdx = this.get 'activeIndex');

//如果当前项是活动索引,返回活动类
if(idx === activeIdx){
return'active-class ';
}

//否则返回没有类
return'';
} .property('activeIndex')

操作:{
selectMenuItem:f unction(){
this.sendAction('selectMenuItemAction',this.get('index'));
}
}
})

然后使用它:

  {{#sideMenuItems中的每个菜单项}} 
{{#menu-item index = _view.contentIndex activeIndex = selectedMenuInde​​x selectMenuItemAction =selectMenuItem}}
{{menuItem.text}}
{{/ menu-item}}
{{/ each}}

控制器:

  Ember.ObjectController .extend({
selectedMenuInde​​x:0,

actions:{
selectMenuItem:function(itemIndex){
this.set('selectedMenuInde​​x',itemIndex);
}
}
})






由于使用 _view.contentIndex 是一种黑客,您只需传递实际的菜单项,并比较对象引用而不是索引来确定活动项目:



菜单项组件:

  Ember.Component。 extend({

// $ in
activeItem:null,
item:null,
selectMenuItemAction:'',

// local
tagName:'li',
classNameBindings:[' activeClass'],

activeClass:function(){
var item = this.get('item');
var activeItem = this.get('activeItem');

//如果当前项是活动项,返回活动类
if(item === activeItem){
return'active-class';
}

//否则返回没有类
return'';
} .property('activeItem')

动作:{
selectMenuItem:function(){
this.sendAction('selectMenuItemAction',this.get项目'));
}
}
})

然后使用它:

  {{#sideMenuItems中的每个菜单项}} 
{{#menu-item item = menuItem activeItem = selectedMenuItem selectMenuItemAction =selectMenuItem}}
{{menuItem.text}}
{{/ menu-item}}
{{/ each}}
  Ember.ObjectController.extend ({
selectedMenuItem:null,

actions:{
selectMenuItem:function(item){
this.set('selectedMenuItem',item);
}
}
})



这是一个更简单的方法在Ember> 1.13



Ember> 1.13支持内联助手,所以你可以很好地实现这一点。 Ember CLI 1.13还附带 babel ,因此我们可以使用ES6,进一步简化:



控制器:

  Ember.Controller.extend({
selectedMenuInde​​x:0,
menuItems:// ...
actions:{
selectMenuItem(itemIndex){
this.set('selectedMenuInde​​x',itemIndex);
}
}
});

模板:

 code> {{#each menuItems as | item index |}} 
< li class ={{active-class index selectedMenuInde​​x}}{{actionselectMenuItemindex}}>
{{item.text}}
< / li>
{{/ each}}

助手:

  activeClass(params){
const [index,active] = params; //使用ES6解构
return(index === active)? 'active-class':'';
}

这是一个工作的旋转


I have a Ember app with side-menu. The menu items in the html are based on Ember's {{each}} loop. When user select a menu-item I want to add this item active class.

How do I add css class to single item inside Ember's {{each}} According to condition from the controller.

Html/Hbs:

<ul>
   {{#each menuItem in sideMenuItems}}
      <li {{bind-attr class="isActive: active-class"}} {{ action 'selectMenuItem' _view.contentIndex }}>
         {{ menuItem.text }}
      </li>
   {{/each}}
</ul>

Controller:

Ember.ObjectController.extend({
  selectedMenuIndex: 0,
  isActive: function() {
    return (this.get('selectedMenuIndex') == ? ? ? );
  }.property('???'),

  actions: {
    selectMenuItem: function(itemIndex) {
      this.set('selectedMenuIndex', itemIndex);
    }
  }
})

解决方案

When user select a menu-item I want to add this item active class.

Since you are using Ember 1.5, I will first show you a few ways to achieve this for older versions.

The easiest way to do this is to add a flag isActive to the item itself, and use that as the condition for the css class. You can set the flag to true for the clicked item in your selectMenuItem action. If your logic allows only a single item to be active at a time, you must also reset any currently active item's isActive flags to false.

{{#each menuItem in sideMenuItems}}
  <li {{bind-attr class="menuItem.isActive:active-class"}} {{action 'selectMenuItem' _view.contentIndex}}>
     {{menuItem.text}}
  </li>
{{/each}}

Controller:

Ember.ObjectController.extend({

  sideMenuItems: // ... your array of items, each containing an isActive flag

  actions: {
    selectMenuItem: function(itemIndex) {
      var items = this.get('sideMenuItems');
      items.forEach(function(item, idx) {         // go through the items,
          if(idx === itemIndex) {                 // find the clicked item and set it as active
              Ember.set(item, 'isActive', true);
          } else {                                // reset all other items
              Ember.set(item, 'isActive', false);
          }
      });
    }
  }
})   

A more efficient way would be to store the currently active item as a separate variable, this will remove the need to iterate the sideMenuItems array twice:

Controller:

Ember.ObjectController.extend({

  sideMenuItems: // ... your array of items, each containing an isActive flag
  activeMenuItem: null,

  actions: {
    selectMenuItem: function(itemIndex) {
      var items = this.get('sideMenuItems');
      var currActive = this.get('activeMenuItem');
      var nextActive = items.objectAt(itemIndex);

      // if there is a currently active item, deactivate it
      if(currActive) {
        Ember.set(currActive, 'isActive', false);
      }

      // if the user clicked on the currently active item, we just reset the selected item
      // otherwise we update the isActive flag for the clicked item
      if(currActive === nextActive) {
          nextActive = null;
      } else {
         Ember.set(nextActive, 'isActive', true);
      }

      // set the clicked item as the currently active menu item
      this.set('activeMenuItem', nextActive);
  }
})  


Another way would be to create a custom component menu-item that renders your li item with/without a class depending on the active index.

Ember.Component.extend({

    // passed in
    activeIndex: -1,
    index: -1,
    selectMenuItemAction: '',

    // local
    tagName: 'li',
    classNameBindings: ['activeClass'],

    activeClass: function() {
        var idx = this.get('index');
        var activeIdx = this.get('activeIndex');

        // if the current item is the active index, return the active class
        if(idx === activeIdx) {
            return 'active-class';
        }

        // otherwise return no class
        return '';
    }.property('activeIndex')

    actions: {
        selectMenuItem: function() {
            this.sendAction('selectMenuItemAction', this.get('index'));
        }
    }
})

And then use it like:

{{#each menuItem in sideMenuItems}}
    {{#menu-item index=_view.contentIndex activeIndex=selectedMenuIndex selectMenuItemAction="selectMenuItem"}}
        {{menuItem.text}}
    {{/menu-item}}
{{/each}}

Controller:

Ember.ObjectController.extend({
  selectedMenuIndex: 0,

  actions: {
    selectMenuItem: function(itemIndex) {
      this.set('selectedMenuIndex', itemIndex);
    }
  }
})


Since using _view.contentIndex is sort of a hack, you can just pass the actual menu item instead and compare the object references instead of indexes to determine the active item:

Menu item component:

Ember.Component.extend({

    // passed in
    activeItem: null,
    item: null,
    selectMenuItemAction: '',

    // local
    tagName: 'li',
    classNameBindings: ['activeClass'],

    activeClass: function() {
        var item = this.get('item');
        var activeItem = this.get('activeItem');

        // if the current item is the active item, return the active class
        if(item === activeItem) {
            return 'active-class';
        }

        // otherwise return no class
        return '';
    }.property('activeItem')

    actions: {
        selectMenuItem: function() {
            this.sendAction('selectMenuItemAction', this.get('item'));
        }
    }
})

And then use it like:

{{#each menuItem in sideMenuItems}}
    {{#menu-item item=menuItem activeItem=selectedMenuItem selectMenuItemAction="selectMenuItem"}}
        {{menuItem.text}}
    {{/menu-item}}
{{/each}}

Controller:

Ember.ObjectController.extend({
  selectedMenuItem: null,

  actions: {
    selectMenuItem: function(item) {
      this.set('selectedMenuItem', item);
    }
  }
})

Here's a much easier way to do this in Ember > 1.13

Ember > 1.13 supports inline helpers so you can achieve this pretty much how you want it. Ember CLI 1.13 also comes with babel so we can use ES6 as well which allows for further simplifications:

Controller:

Ember.Controller.extend({
  selectedMenuIndex: 0,
  menuItems: // ...
  actions: {
    selectMenuItem(itemIndex) {
      this.set('selectedMenuIndex', itemIndex);
    }
  }
});

Template:

{{#each menuItems as |item index|}}
  <li class="{{active-class index selectedMenuIndex}}" {{action "selectMenuItem" index}}>
  {{item.text}}
  </li>
{{/each}}

Helper:

activeClass(params) {
  const [ index, active ] = params; // use ES6 destructuring
  return (index === active) ? 'active-class': '';
}

Here is a working twiddle

这篇关于根据索引,如何将Css类添加到Ember的{{#each}}循环中的项目? - Ember.js的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆