2013-06-06 57 views
0

我想在knockout.js中解决以下问题:我有三个输入; pricequantitytotal,在这里我想设置Knockout.js中的相互递归字段

total = price * quantity 

当我更新pricequantity,但我也想设置

price = total/quantity 

如果我更新total

我原本是用一个计算的observable做这个,但是这只能工作,但是我有一个四舍五入的问题。例如。如果我做

quantity(3) 
total(100) 

我想price设定为33.33,只有两位小数,而total仍然应该设置为100,这样的身份total = price * quantity不做得比较保留。

在我所计算的可观察方法中,total在这种情况下将被设置为99.99。 这使得这种情况与文档中的全名/名字/姓氏示例不同。

本质上,price/total字段是相互递归的。除了手动订阅,我无法找到解决此问题的好方法,但这种感觉非常单一,意味着我必须手动处理一堆订阅等。

回答

3

我已经做了类似的事情,价值“(即数量,价格和总量),在表单字段上跟踪焦点事件,并使用ko.computed()重新计算(但不是在选择当前字段的情况下)并格式化形成。

这一句话的描述听起来很复杂,但并不是那种复杂的代码明了。

的JavaScript:

var Model = function() { 
    var self = this; 

    self.quantity = ko.observable(0); 
    self.price = ko.observable(0); 
    self.price.selected = ko.observable(false); 
    self.total = ko.observable(0); 
    self.total.selected = ko.observable(false); 

    self.formattedPrice = ko.computed({ 
     read: function() { 
      if (!self.price.selected()) { 
       var total = self.total() || 0; 
       var quantity = self.quantity() || 0; 
       var value = total/quantity; 
       self.price(isNaN(value) ? 0 : value); 
      } 
      return '$' + self.price().toFixed(2); 
     }, 
     write: function (value) { 
      value = parseFloat(value.replace(/[^\.\d]/g, "")); 
      self.price(isNaN(value) ? 0 : value); 
     } 
    }); 

    self.formattedTotal = ko.computed({ 
     read: function() { 
      if (!self.total.selected()) { 
       var quantity = self.quantity() || 0; 
       var price = self.price() || 0; 
       var value = quantity * price; 
       self.total(isNaN(value) ? 0 : value); 
      } 
      return '$' + self.total().toFixed(2); 
     }, 
     write: function (value) { 
      value = parseFloat(value.replace(/[^\.\d]/g, "")); 
      self.total(isNaN(value) ? 0 : value); 
     } 
    }); 
}; 

ko.applyBindings(new Model()); 

在你绑定的价格和总像这样的HTML:如果你想看到一个工作在jsfiddle

<input data-bind="value: formattedPrice, hasfocus: price.selected" />

<input data-bind="value: formattedTotal, hasfocus: total.selected" />

代码例。

0

感谢您的回答。只是供参考,这是我目前的解决方案,可能会坚持下去,除非它给我的问题。

var self = this; 
    this.price = ko.observable().extend({numeric: 2}); 
    this.quantity = ko.observable(1).extend({ numeric: 2 }); 
    this.total = ko.observable(1).extend({ numeric: 2 }); 

    var unsub_total = this.total.subscribe(function (total) { 
     if (self.quantity() != 0) 
      self.price(total/self.quantity()) 
    }); 

    // setting quantity will update both price and total 
    var unsub_qty = this.quantity.subscribe(function (qty) { 
     self.total(self.price() * qty); 
    }); 

    var unsub_price = this.price.subscribe(function (price) { 
     self.total(price * self.quantity()); 
    }); 

    this.unsub = function() { unsub_total(); unsub_price(); unsub_qty(); };