Javascript 观察Ember.ArrayController中的任何Ember.ObjectController何时更改

Javascript 观察Ember.ArrayController中的任何Ember.ObjectController何时更改,javascript,ember.js,ember-cli,Javascript,Ember.js,Ember Cli,我正在尝试在一个余烬应用程序中设置集体行动复选框(比如删除所选项目)。这样做的目的是在选中任何一个复选框时,显示或隐藏一个“体量动作”下拉列表。我还没有输入下拉列表,因为我不知道如何观察数组中的所有元素。我怎样才能: 设置阵列控制器,使其观察所有客户端对象 获取更改时选中的项目数 另外:我是否按照惯例与客户itemController接洽 app/templates/clients.hbs <section id="clients"> <h4>my clients

我正在尝试在一个余烬应用程序中设置集体行动复选框(比如删除所选项目)。这样做的目的是在选中任何一个复选框时,显示或隐藏一个“体量动作”下拉列表。我还没有输入下拉列表,因为我不知道如何观察数组中的所有元素。我怎样才能:

  • 设置阵列控制器,使其观察所有客户端对象
  • 获取更改时选中的项目数
  • 另外:我是否按照惯例与客户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}}
    
    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');
      });
    });
    
    import Ember from 'ember';
    export default Ember.Route.extend({
        model: function() {
            return this.store.find('client');
        }
    });
    
    import DS from 'ember-data';
    export default DS.Model.extend({
      clientName: DS.attr('string'),
      clientEmail: DS.attr('string')
    });
    
    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')
    });
    
    import Ember from 'ember';
    export default Ember.ObjectController.extend({
        markedForDeletion: true,
        markedForDeletionChanged: function(){
            // This fires correctly
            console.log('markedForDeletion object changed');
        }.observes('markedForDeletion')
    });
    
    <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}}
    
    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')
    });
    
    app/routes/clients.js

    <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}}
    
    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');
      });
    });
    
    import Ember from 'ember';
    export default Ember.Route.extend({
        model: function() {
            return this.store.find('client');
        }
    });
    
    import DS from 'ember-data';
    export default DS.Model.extend({
      clientName: DS.attr('string'),
      clientEmail: DS.attr('string')
    });
    
    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')
    });
    
    import Ember from 'ember';
    export default Ember.ObjectController.extend({
        markedForDeletion: true,
        markedForDeletionChanged: function(){
            // This fires correctly
            console.log('markedForDeletion object changed');
        }.observes('markedForDeletion')
    });
    
    <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}}
    
    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')
    });
    
    app/models/client.js

    <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}}
    
    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');
      });
    });
    
    import Ember from 'ember';
    export default Ember.Route.extend({
        model: function() {
            return this.store.find('client');
        }
    });
    
    import DS from 'ember-data';
    export default DS.Model.extend({
      clientName: DS.attr('string'),
      clientEmail: DS.attr('string')
    });
    
    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')
    });
    
    import Ember from 'ember';
    export default Ember.ObjectController.extend({
        markedForDeletion: true,
        markedForDeletionChanged: function(){
            // This fires correctly
            console.log('markedForDeletion object changed');
        }.observes('markedForDeletion')
    });
    
    <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}}
    
    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')
    });
    
    app/controllers/clients.js

    <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}}
    
    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');
      });
    });
    
    import Ember from 'ember';
    export default Ember.Route.extend({
        model: function() {
            return this.store.find('client');
        }
    });
    
    import DS from 'ember-data';
    export default DS.Model.extend({
      clientName: DS.attr('string'),
      clientEmail: DS.attr('string')
    });
    
    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')
    });
    
    import Ember from 'ember';
    export default Ember.ObjectController.extend({
        markedForDeletion: true,
        markedForDeletionChanged: function(){
            // This fires correctly
            console.log('markedForDeletion object changed');
        }.observes('markedForDeletion')
    });
    
    <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}}
    
    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')
    });
    
    app/controllers/clients/client.js

    <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}}
    
    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');
      });
    });
    
    import Ember from 'ember';
    export default Ember.Route.extend({
        model: function() {
            return this.store.find('client');
        }
    });
    
    import DS from 'ember-data';
    export default DS.Model.extend({
      clientName: DS.attr('string'),
      clientEmail: DS.attr('string')
    });
    
    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')
    });
    
    import Ember from 'ember';
    export default Ember.ObjectController.extend({
        markedForDeletion: true,
        markedForDeletionChanged: function(){
            // This fires correctly
            console.log('markedForDeletion object changed');
        }.observes('markedForDeletion')
    });
    
    <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}}
    
    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')
    });
    

    编辑:问了类似的问题,但恐怕答案对我没有多大帮助。

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

    注意:在深入研究解决方案之前,需要注意的是,ArrayController、ObjectController和ItemController都被弃用

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

    <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}}
    
    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');
      });
    });
    
    import Ember from 'ember';
    export default Ember.Route.extend({
        model: function() {
            return this.store.find('client');
        }
    });
    
    import DS from 'ember-data';
    export default DS.Model.extend({
      clientName: DS.attr('string'),
      clientEmail: DS.attr('string')
    });
    
    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')
    });
    
    import Ember from 'ember';
    export default Ember.ObjectController.extend({
        markedForDeletion: true,
        markedForDeletionChanged: function(){
            // This fires correctly
            console.log('markedForDeletion object changed');
        }.observes('markedForDeletion')
    });
    
    <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}}
    
    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')
    });
    
    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}}
    
    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');
      });
    });
    
    import Ember from 'ember';
    export default Ember.Route.extend({
        model: function() {
            return this.store.find('client');
        }
    });
    
    import DS from 'ember-data';
    export default DS.Model.extend({
      clientName: DS.attr('string'),
      clientEmail: DS.attr('string')
    });
    
    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')
    });
    
    import Ember from 'ember';
    export default Ember.ObjectController.extend({
        markedForDeletion: true,
        markedForDeletionChanged: function(){
            // This fires correctly
            console.log('markedForDeletion object changed');
        }.observes('markedForDeletion')
    });
    
    <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}}
    
    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中多选复选框功能实现的工作示例

    基本上,当循环遍历数组中的每个项时,itemController将自身的引用发送给parentController,parentController在数组中维护这些引用。此处,
    isChecked
    属性在每个itemController中定义,而不是附加到数组成员。 我们在生产代码中使用这种方法

    另一种方法是使用
    ObjectProxy
    并在新数组的每个数组项上附加
    isChecked
    属性,并观察它

    例如,如果
    颜色
    是数组,则

    var newColors = colors.map(function(color){
     return Ember.ObjectProxy.create({
       isChecked: false, 
       content: color
       } 
    )};
    
    通过这种方式,我们创建了带有
    isChecked
    属性的newColors数组,我们可以循环使用该属性,并且我们没有触及单个项