2017-01-17 7 views
2

У меня есть атрибут модели, который является объектом:Слушайте изменения от вложенной модели атрибутов

name : "testing", 
orderCondition: { 
    minOrderAmount: 20, 
    deliveryCostRequire: "MIN_ORDER_AMOUNT", 
    deliveryCostAmount: 5.55 
} 

Когда я использую listenTo, как это, функция render не называется

this.listenTo(this.model, "change:orderCondition", this.render); // NO FIRING 

Но когда я используйте listenTo по другим атрибутам, он работает.

this.listenTo(this.model, "change:name", this.render); // FIRING 

Почему listenTo не видит изменений в вложенных объектов, но увидеть их в простые атрибуты?

ответ

2

Простой способ заставить атрибут вложенного объекта запускать событие change - это заменить весь объект новым. Самый простой способ с простой set:

model.set('orderCondition', _.extend({}, model.get('orderCondition'), { 
    deliveryCostRequire: "TOTAL_ORDER_AMOUNT" 
})); 

Создание функции для установки вложенных атрибутов на модели является хорошим способом для инкапсуляции этой сложности.

var Model = Backbone.Model.extend({ 

    setDeliveryCostRequire: function(value, options) { 
     // build a new object for 'orderCondition' 
     var newOrderCondition = _.extend({}, this.get('orderCondition'), { 
      deliveryCostRequire: value 
     }); 
     // replace 'orderCondition' with the new object. 
     this.set({ orderCondition: newOrderCondition }, options); 
     // optionally trigger a custom event for it. 
     this.trigger('change:deliveryCostRequire', this, value, options); 
     return this; 
    }, 
}); 

Это основная концепция.

Backbone.epoxy является двухсторонней библиотекой связывания, которая также предлагает рассчитанные поля для моделей, которые достигают того же, что и выше, но с дополнительным преимуществом - быть полностью прозрачным извне модели.

var Model = Backbone.Model.extend({ 
    computeds: { 
     deliveryCostRequire: { 
      deps: ['orderCondition'], 
      get: function(orderCondition) { 
       return orderCondition && orderCondition.deliveryCostRequire; 
      }, 
      set: function(value) { 
       return { 
        orderCondition: _.extend({}, this.get('orderCondition'), { 
         deliveryCostRequire: value 
        }) 
       }; 
      }, 
     }, 
     deliveryCostAmount: { /* ...other computed... */ }, 
    } 
}); 

С помощью этой модели, вы можете сделать следующее:

model.set('deliveryCostRequire', 'TOTAL_ORDER_AMOUNT'); 
model.get('deliveryCostRequire'); 
this.listenTo(model, 'change:deliveryCostRequire', this.render); 

Я также сделал a simple way to bubble up events of nested models and collections.

0

Просто потому, что Backbone не работает с вложенными объектами. Например, вы не можете присвоить атрибуту свойства объекта model.set().

Ваш this.listenTo только слушает изменение всего объекта, а не его свойств.

Вы можете попробовать использовать библиотеки, такие как backbone-deep-model для поддержки вложенных объектов.

+0

Я могу установить атрибут с помощью model.get как this 'this.model.get (" orderCondition "). MinOrderAmount = Некоторое значение;' –

+2

@ ThePrzemyslaw94 '.' не является базовым сеттером. Магистраль позволяет вам получить доступ к прямому атрибуту свойств, здесь 'this.model.get (« orderCondition »)' события и что-то еще не работает ниже этого уровня по умолчанию. –