2013-04-13 25 views
0

我想创建“排序”按钮,当点击使用Ember.js时改变排序和CSS类。如何让Ember.js的bindAttr刷新?

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

我错过了什么?

这是我的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(); 
}); 

版本:烬:1.0.0-rc.2,车把:1.0.0-RC .3

+0

计算属性? – MilkyWayJoe

+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/

+0

因此,使用this.get('propertyName')会导致Ember登记订阅更改通知? –

+0

A ['Computed Property'](http:// emberjs。com/api/classes/Ember.ComputedProperty.html)和'property'装饰器,将会缓存函数的返回值,并且有点像观察者。订阅此观察者的应用程序的所有部分(例如Handlebars模板中的该属性的调用)将在该值发生更改时通知,并将执行自己的工作流以对值更改作出反应。 – MilkyWayJoe

0

乔的帮助后,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'); 
    }, 

});