2014-02-13 102 views
0

我正在使用基諾爲項目創建一個基本的AJAX購物車,並且包含在視圖模型內的可觀察集合中的單個產品的成本需要更新屬性在視圖模型上更新。我一直在嘗試各種解決方案很多小時,我希望有人能指出我正確的方向。我已經包含了一個jsfiddle。從視圖模型的屬性敲除更新可觀察集合

http://jsfiddle.net/g8BLj/3/

var product = function (title, operationName, description, parent) { 
    this.title = title; 
    this.operationName = operationName; 
    this.description = description; 
    this.cost = 9; 
    this.count = ko.observable(parent.recordCount); 
    this.subtotal = ko.computed(function() { 
    return this.count * this.cost; 
    }).bind(this); 
}; 

order = function() { 
var listName = ko.observable("not defined"), 
    listId = ko.observable("not defined"), 
    recordCount = ko.observable("not defined"), 
    products = [ 
    new product('Product1', 'EMAIL_VER_DELIVERABLE', 'Description.', this), 
    new product('Product2', 'EMAIL_BASIC_NO_SUPRESSION_W_VERIFICATION', 'Description.', this), 
    new product('Product3', 'PHONE_PREM', 'Description.', this)], 
    total = function() { 
     var total = 0; 
     $.each(this.products(), function() { 
      total += this.subtotal(); 
     }); 
     return total; 
    }; 

// anything in the return block is considered public, anything above is private 
return { 
    listName: listName, 
    listId: listId, 
    recordCount: recordCount, 
    products: products, 
    total: total 
}; 
}(); 

ko.applyBindings(order); 

// when this value changes the product Cost needs to be updated 
order.listName('test list') 
order.listId(1) 
order.recordCount(100) 

謝謝, 克里斯

回答

0

沒有與「本」的範圍,其導致問題的幾個問題。

this.subtotal = ko.computed(function() { 
    return this.count * this.cost; 
}).bind(this); 

正確的方式來獲得環境範圍正確的是通過「本」到ko.computed作爲第二個參數。另外,count是您需要評估它的可觀察值。

this.subtotal = ko.computed(function() { 
    return this.count() * this.cost; 
}, this); 

產品變量傳遞「這個」到產品的構造。此時的環境是窗口,因爲您正在使用匿名函數/顯示模塊模式。

所以當

this.count = ko.observable(parent.recordCount); 

求值,父窗口,所以總記錄==不確定的。

如果要繼續使用揭示模塊模式,則需要對訂單函數進行微調以聲明您的返回對象(「obj」),然後創建產品。

您還應該聲明整個屬性爲ko.computed。我使用map/reduce而不是$ .each,但這是個人偏好。

完成此操作後,它會顯示產品類的count屬性的更多問題。 parent.recordCount是一個可觀察對象,因此您要創建一個可觀察對象,其值爲可觀察對象,而不是可觀察對象的值。只需將觀察值賦給一個count屬性即可。


var product = function (title, operationName, description, parent) { 
    this.title = title; 
    this.operationName = operationName; 
    this.description = description; 
    this.cost = 9; 
    this.count = parent.recordCount; 
    this.subtotal = ko.computed(function() { 
     return this.count() * this.cost; 
    }, this); 
}; 

order = function() { 
    var 
    listName = ko.observable("not defined"), 
     listId = ko.observable("not defined"), 
     recordCount = ko.observable("not defined"), 
     products = []; 

    var obj = { 
     listName: listName, 
     listId: listId, 
     recordCount: recordCount, 
     products: products 
    } 

    // now we have an object to push into the product class 
    products.push(
     new product('Product1', 'EMAIL_VER_DELIVERABLE', 'Description.', obj), 
     new product('Product2', 'EMAIL_BASIC_NO_SUPRESSION_W_VERIFICATION', 'Description.', obj), 
     new product('Product3', 'PHONE_PREM', 'Description.', obj) 
     ); 

    obj.total = ko.computed(function() { 
     return this.products 
      .map(function(item) { return item.subtotal(); }) 
      .reduce(function(runningTotal, subtotal) { return runningTotal + subtotal; 
     }, 0); 
    }, obj); 

    // anything in the return block is considered public, anything above is private 
    return obj; 
}(); 

ko.applyBindings(order); 

// when this value changes the product Cost needs to be updated 
order.listId(1); 
order.listName('test list'); 
order.recordCount(100); 
0

我認爲,解決這個問題最重要的事情,就是用訂閱order.recordCount的變化,而不是發送order作爲參數傳遞給product
你可以寫這樣的事情:

recordCount.subscribe(function (newValue) { 
    ko.utils.arrayForEach(products, function (product) { 
     product.count(newValue); 
    }) 
}); 

此外,你應該改變product.subtotal計算:

this.subtotal = ko.computed(function() { 
    return this.count() * this.cost; 
}, this);