如何让Ember.js的bindAttr刷新?

时间:2013-04-13 18:31:37

标签: css ember.js

我正在尝试创建“排序依据”按钮,这些按钮在使用Ember.js单击时会更改排序和css类。

排序部分和初始类分配有效,但是,当我更新依赖属性时,类分配不会刷新。

我错过了什么?

这是我的HTML:

<script type="text/x-handlebars" data-template-name="sort-option-item">
    <dd {{bindAttr class="IsActive:active IsDesc:reversed"}}
        {{action sortBy on="click"}}><a href="#">{{Name}}</a></dd>
</script>

<script type="text/x-handlebars">
    {{#each option in controller.sortOptions}}
        {{view App.SortOptionView controllerBinding="option"}}
    {{/each}}
</script>

这是我的Javascript:

var App = null;

$(function () {

    App = Ember.Application.create();

    // Define Types:

    App.SortOptionCtrl = Ember.Controller.extend({
        Name: null,
        Predicate: null,
        Controller: null,
        IsActive: false,
        IsDesc: false,
        sortBy: function () {
            if (this.Controller != null)
                this.Controller.sortBy(this.Predicate);
        },
        Check: function () {
            this.IsActive = this.Controller != null
                            && this.Controller.isSortedBy(this.Predicate);
            this.IsDesc = this.Controller != null
                          && this.Controller.isSortedDescBy(this.Predicate);
            // adding an alert(this.IsActive); here
            // proves that the function is indeed called and works as expected
        }
    });

    App.ProductsController = Ember.ArrayController.extend({

        initialized: false,
        content: [],
        viewContent: [],
        sortProperties: ['Order'],
        sortAscending: true,
        sortOptions: [],

        initialize: function () {

            if (this.initialized == true)
                return;

            this.initialized = true;
            var ctrl = this;

            this.sortOptions.pushObject(App.SortOptionCtrl.create({
                Name: 'Unsorted',
                Predicate: null,
                Controller: ctrl,
            }));
            this.sortOptions.pushObject(App.SortOptionCtrl.create({
                Name: 'By Name',
                Predicate: 'Name',
                Controller: ctrl,
            }));
            this.sortOptions.pushObject(App.SortOptionCtrl.create({
                Name: 'By Date',
                Predicate: 'Date',
                Controller: ctrl,
            }));

            this.sortOptions.forEach(function (opt) { opt.Check(); });
        },

        load: function () {

            this.initialize();
            // ....
        },

        sortBy: function (predicate) {

            var prevPredicate = this.sortProperties[0];

            if (predicate == prevPredicate && predicate != null) {
                this.sortAscending = !(this.sortAscending);
            }
            else {
                this.sortAscending = true;
            }

            this.sortProperties.length = 0;

            if (predicate)
                this.sortProperties.pushObject(predicate);
            else
                this.sortProperties.pushObject('Order');

            this.sortOptions.forEach(function (opt) { opt.Check(); });
        },

        isSortedBy: function (predicate) 
        {
            if (predicate == null)
                predicate = 'Order';

            var activePredicate = this.sortProperties[0];

            if (predicate == activePredicate) {
                return true;
            }
            else {
                return false;
            }
        },

        isSortedDescBy: function (predicate) {

            if (predicate == null)
                predicate = 'Order';

            var activePredicate = this.sortProperties[0];

            if (predicate == activePredicate) {
                if (this.sortAscending)
                    return false;
                else
                    return true;
            }
            else {
                return false;
            }
        },

    });

    App.SortOptionView = Ember.View.extend({
        templateName: 'sort-option-item'
    });

    // Create Instances:

    App.productsController = App.ProductsController.create({
    });

    App.productsController.load();

    App.initialize();
});

版本:Ember:1.0.0-rc.2,把手:1.0.0-rc.3

2 个答案:

答案 0 :(得分:2)

如果您希望视图对控制器中发生的任何事情做出反应,则应创建计算属性(通过fn(){}.property('dependency'))。但是,为了使计算属性正常工作,您需要使用Ember的get()set()属性访问器。

在您的代码中,您正在执行

之类的操作
this.IsActive = this.Controller != null && 
                this.Controller.isSortedBy(this.Predicate);

当你应该做这样的事情时:

this.set('active',
     this.get('controller') != null &&
     this.get('controller').isSortedBy(this.get('Predicate'))
);

您可能已经注意到此代码值设置为active,但模板正在侦听isActive。该属性已更改为计算属性:

isActive: function() {
    return this.get('active');
}.property('active')

它将侦听active属性中的更改,并且每当发生这种情况时,它将缓存新值,并通知所有订阅者对象刷新/更新。

指示使用Ember的getset访问器,以便正确使用使这一系列事件成为可能的可观察对象。

我已根据需要修改了应用getset的示例。 您可以在这个小提琴中看到它: http://jsfiddle.net/schawaska/fRMYu/

答案 1 :(得分:0)

在Joe的帮助下,更多地阅读了Ember的手册并清理了我的代码,我得到了这个分拣机解决方案:

排序选项控制器:

App.SortOptionCtrl = Em.Controller.extend({
    Name: null,
    Predicate: null,

    _isActive: false,
    isActive: function () {
        return this.get('_isActive');
    }.property('_isActive'),

    _isDesc: false,
    isDesc: function () {
        return this.get('_isDesc');
    }.property('_isDesc'),

    controller: null,

    updateState: function () {
        if (!this.Predicate) {
            this.set('_isActive', (this.get('controller')
                .get('activePredicate') == null));
            this.set('_isDesc', false);
        }
        else {
            this.set('_isActive', (this.get('controller')
                .get('activePredicate') == this.Predicate));
            this.set('_isDesc', (this.get('_isActive')
                && !this.get('controller').get('sortAscending')));
        }
    }.observes('controller.activePredicate', 'controller.sortAscending'),

    sortBy: function () {
        if (this.get('controller') != null) {
            this.get('controller').sortBy(this.Predicate);
        }
    },
});

产品控制器:

App.ProductsController = Ember.ArrayController.extend({

    content: [],
    viewContent: [],
    activePredicate: null,
    sortProperties: ['Order'],
    sortAscending: true,
    sortOptions: [],

    filter: function (obj) {
        return true;
    },

    init: function () {

        this._super();

        var ctrl = this;

        this.sortOptions.pushObject(App.SortOptionCtrl.create({
            Name: 'Unsorted',
            Predicate: null,
            controller: ctrl,
        }));
        this.sortOptions.pushObject(App.SortOptionCtrl.create({
            Name: 'By Name',
            Predicate: 'Name',
            controller: ctrl,
        }));
        this.sortOptions.pushObject(App.SortOptionCtrl.create({
            Name: 'By Date',
            Predicate: 'Date',
            controller: ctrl,
        }));

        this.sortOptions.forEach(function (opt) {
            opt.updateState();
        });
    },

    sortBy: function (predicate) {

        var prevPredicate = this.sortProperties[0];

        if (predicate == prevPredicate && predicate != null) {
            this.set('sortAscending', !(this.get('sortAscending')));
        }
        else {
            this.set('sortAscending', true);
        }

        this.set('activePredicate', predicate);
        this.set('sortProperties.length', 0);

        if (predicate)
            this.get('sortProperties').pushObject(predicate);
        else
            this.get('sortProperties').pushObject('Order');
    },

});