簡體   English   中英

如何根據索引將Css類添加到Ember的{{#each}}循環中的項目? -Ember.js

[英]How to add Css Class to item inside Ember's {{#each}} loop, according to index? - Ember.js

我有一個帶有側菜單的Ember應用程序。 html中的菜單項基於Ember的{{each}}循環。 當用戶選擇菜單項時,我要添加此項目活動類。

如何根據控制器的條件將css類添加到Ember的{{each}}中的單個項目中。

Html / Hbs:

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

控制器:

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

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

當用戶選擇菜單項時,我要添加此項目活動類。

由於您使用的是Ember 1.5,因此我將首先向您展示一些針對較舊版本實現此目標的方法。

最簡單的方法是向項目本身添加一個標志isActive ,並將其用作css類的條件。 您可以在selectMenuItem操作selectMenuItem單擊項的標志設置為true 如果您的邏輯一次只允許一個項目處於活動狀態,則還必須將任何當前活動項目的isActive標志重置為false

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

控制器:

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);
          }
      });
    }
  }
})   

一種更有效的方法是將當前活動的項目存儲為單獨的變量,這將消除對sideMenuItems數組進行兩次迭代的需要:

控制器:

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);
  }
})  

另一種方法是創建一個自定義組件menu-item ,該menu-item根據活動索引呈現帶/不帶類的li項目。

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'));
        }
    }
})

然后像這樣使用它:

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

控制器:

Ember.ObjectController.extend({
  selectedMenuIndex: 0,

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

由於使用_view.contentIndex有點_view.contentIndex ,因此您可以只傳遞實際的菜單項,然后比較對象引用而不是索引來確定活動項:

菜單項組成:

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'));
        }
    }
})

然后像這樣使用它:

{{#each menuItem in 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({
  selectedMenuIndex: 0,
  menuItems: // ...
  actions: {
    selectMenuItem(itemIndex) {
      this.set('selectedMenuIndex', itemIndex);
    }
  }
});

模板:

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

幫手:

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

這是一個工作中的小玩意兒

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM