观察 Ember.ArrayController 中的任何 Ember.ObjectController 何时发生变化

Observe when any Ember.ObjectController in Ember.ArrayController changes

我正在尝试在 Ember 应用程序中设置批量操作复选框(例如删除所选项目)。这个想法是在选中任何一个复选框时显示或隐藏大规模操作下拉列表。我还没有放入下拉列表,因为我不知道如何观察数组中的所有元素。我怎样才能:

  1. 设置 Array 控制器以观察所有客户端对象
  2. 获取变化时勾选的项目数
  3. 另外:我是否遵循了处理客户端 itemController 的惯例?

app/templates/clients.hbs

<section id="clients">
    <h4>my clients</h4>
    <ul>
    {{#each itemController="clients/client"}}
        <li>
            {{input type="checkbox" name="markedForDeletion" checked=markedForDeletion}}
            {{#link-to 'clients.show' this}}
                {{clientName}}
            {{/link-to}}
        </li>
    {{/each}}

    </ul>
</section>
{{#link-to 'clients.new'}}Add client{{/link-to}}
{{outlet}}

router.js

import Ember from 'ember';
import config from './config/environment';

var Router = Ember.Router.extend({
  location: config.locationType
});

export default Router.map(function() {
  this.resource('clients', function() {
    this.route('show', {path: '/:client_id'});
    this.route('new');
  });
});

app/routes/clients.js

import Ember from 'ember';
export default Ember.Route.extend({
    model: function() {
        return this.store.find('client');
    }
});

app/models/client.js

import DS from 'ember-data';
export default DS.Model.extend({
  clientName: DS.attr('string'),
  clientEmail: DS.attr('string')
});

app/controllers/clients.js

import Ember from 'ember';
export default Ember.ArrayController.extend({
    checkBoxesChanged: function() {
    // This fires only once, when the /clients/ route is activated
    console.log('markedForDeletion in array changed');
  }.observes('@each.clients')
});

app/controllers/clients/client.js

import Ember from 'ember';
export default Ember.ObjectController.extend({
    markedForDeletion: true,
    markedForDeletionChanged: function(){
        // This fires correctly
        console.log('markedForDeletion object changed');
    }.observes('markedForDeletion')
});

编辑:问过类似的问题 here,但恐怕答案对我帮助不大。

对此有几个解决方案。由于您的解决方案只需要额外 属性 被检查,我认为 ObjectProxy 可以满足您的需求。但是,如果您需要更多功能,那么组件会更合适。

注意:不过,在我们深入研究解决方案之前,重要的是要注意 ArrayController、ObjectController 和 ItemController 都已被弃用。

由于我们不会使用 itemController,您可以删除 app/controllers/clients/client.js

app/templates/clients.hbs

<section id="clients">
    <h4>my clients</h4>
    <ul>
    {{#each clientsWithMarker as |client|}}
        <li>
            {{input type="checkbox" name="markedForDeletion" checked=client.markedForDeletion}}
            {{#link-to 'clients.show' client}}
                {{client.clientName}}
            {{/link-to}}
        </li>
    {{/each}}

    </ul>
</section>
{{#link-to 'clients.new'}}Add client{{/link-to}}
{{outlet}}

app/controllers/clients.js

import Ember from 'ember';
export default Ember.Controller.extend({
    clientsWithMarker: Ember.computed.map('model', function(client) {
        return Ember.ObjectProxy.create({
            content: client,
            checked: false
        });
    }),

    // This computed property returns an array of ObjectProxies that
    // are checked. It is recalculated automatically
    checkedClients: Ember.computed.filterBy('clientsWithMarker', 'checked', true),

    checkBoxesChanged: function() {
    // This fires only once, when the /clients/ route is activated
    console.log('markedForDeletion in array changed');
  }.observes('clientsWithMarker.@each.checked')
});

这个应该有效,但我还没有实际测试这个特定的代码。

这是 ember 中 Multi-Select 复选框功能实现的工作示例。

http://alexdiliberto.com/posts/ember-toggle-all-checkbox/

http://emberjs.jsbin.com/coliwiwa/5/edit?html,css,js,output

基本上,当遍历数组中的每个项目时,itemController 将其自身的引用发送到 parentController,parentController 在数组中维护这些引用。这里 isChecked 属性 是在每个 itemController 内部定义的,而不是附加到数组 members。 我们在生产代码中使用这种方法。

替代方法可以是使用 ObjectProxy 并在新数组的每个数组项上附加 isChecked 属性,然后观察它。

例如。如果 colors 是数组那么

var newColors = colors.map(function(color){
 return Ember.ObjectProxy.create({
   isChecked: false, 
   content: color
   } 
)};

通过这种方式,我们创建了带有 isChecked 属性 的 newColors 数组,我们可以对其进行循环,我们还没有触及单个项目。