Ember.js 余烬阵列控制器中的互斥

Ember.js 余烬阵列控制器中的互斥,ember.js,Ember.js,我有一个数组控制器中的项目列表。单击一个项目会使其处于“活动”状态,但我希望每次只激活一个项目(类似于单选按钮) 我通过将活动项存储在计算属性中,然后在阵列控制器上的操作中切换其活动状态来实现这一点,请参见: 但是,这不适用于通过其他方式(即不通过操作)激活项目的情况 我尝试过观察isActive更改(使用.observesBefore('@each.isActive')),并翻转activeItem的状态,但当然,这种方法会导致无限循环 有更好的方法吗?基于您的TogCollective实现的

我有一个数组控制器中的项目列表。单击一个项目会使其处于“活动”状态,但我希望每次只激活一个项目(类似于单选按钮)

我通过将活动项存储在计算属性中,然后在阵列控制器上的操作中切换其活动状态来实现这一点,请参见:

但是,这不适用于通过其他方式(即不通过操作)激活项目的情况

我尝试过观察
isActive
更改(使用
.observesBefore('@each.isActive')
),并翻转
activeItem
的状态,但当然,这种方法会导致无限循环


有更好的方法吗?

基于您的TogCollective实现的可能解决方案可用

如果仅使用TOGGELACTIVE控制器方法更新“active”标志,则此解决方案有效。到目前为止,控制器表示状态,提供api以正确更新其数据是有意义的

App.IndexController = Ember.ArrayController.extend({
      itemController: 'item',

      activeItem: function() {
        return this.findBy('isActive');
      }.property('@each.isActive'),

      toggleActiveModel: function(model) {
        var controller = this.findBy('model', model);
        this._toggleActive(controller);
      },

      _toggleActive: function(controller) {
        var previouslyActive = this.get('activeItem');
        if(previouslyActive && previouslyActive !== controller) {
          previouslyActive.set('isActive', false);
        } 
        controller.set('isActive', !controller.get('isActive'));

      },

      actions: {
        toggleActive: function(controller) {
           this._toggleActive(controller); 
        },
        toggle: function(modelValue) {
           this.toggleActiveModel(modelValue); 
        }

      }
    });

这可以使用和观察者的组合来解决

Ember.reduceComputed
中的
removedItem
addedItem
回调可以访问已更改的对象,以及
instanceMeta
,可用于存储“活动”项:

App.IndexController = Ember.ArrayController.extend({

  itemController: 'item',

  activeItem: Ember.reduceComputed('@this.@each.isActive', {

    initialValue: null,

    removedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
      if (item.get('isActive')) {
        var previousActiveItem = instanceMeta.activeItem;
        if (previousActiveItem) previousActiveItem.set('isActive', false);
        return instanceMeta.activeItem = item;
      }
      return instanceMeta.activeItem = null;
    },

    addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
      return instanceMeta.activeItem;
    }
  })
  …
但是,如果未在任何位置访问
activeItem
,则永远不会调用
removedItem
addedItem
,因此项目将保持活动状态,直到手动切换。要解决此问题,可以设置观察者在
isActive
属性更改时调用
this.get('activeItem')

setActiveItem: function () {
  this.get('activeItem');
}.observes('@each.isActive')
请参阅更新的jsbin:


相关:David Hamilton在上的演示。

感谢您的回答,但是,必须通过阵列控制器更新item controller上的
isActive
属性并不理想。是否有办法预先选择“红色”作为活动属性?