2

問題

shoppingcartビューモデルのビューモデルがobservableArrayありcartitemsます。

subtotalビューモデルのプロパティを更新するとき、cartitemsビューモデルのcomputedObservableshoppingcartを更新する必要がありますが、更新をトリガーする方法がわかりません

function shoppingcart() {
    var self = this;
    self.cartItems = ko.observableArray([]);
    self.grandTotal = ko.computed(function() {
        var total = 0;
        _.each(self.cartItems(), function (item) {
            total += item.subTotal;
        }
    }

    //inital load of the data
    dataservice.loadCartItems(self.cartItems);
}



function cartItem() {
    var self = this;
    self.quantity = ko.observable(0);
    self.price = 0.00;

    self.subTotal = ko.computed(function() {
        return self.price * self.quantity();
    }
}

次に、私の見解では、これに似たものがあります

<ul data-bind='foreach: cartItems'>
    <!--other stuff here -->
    <input type='text' data-bind="value: quantity, valueUpdate: 'afterkeydown'"/>
</ul>

<span data-bind='value: grandTotal'></span>

これは機能すると思われますが、どこかを台無しにしただけですか、それともこれを更新するには何か他のものを追加する必要がありますか?

現在、テキスト ボックス内の数量が変更されても、スパン内の grandTotal は更新されません。これは、この子プロパティが実際には、cartItems コレクションが変更されたものとしてカウントされないためだと思います。

ここでコレクションの更新をトリガーする良い方法は何ですか?

4

2 に答える 2

2

grandTotal計算から何も返していませんでした。また、戻り値の代わりにsubTotal実行中の関数を追加しようとしていました。total計算された on を呼び出すには、括弧を付けて呼び出す必要がありますcartItem

function shoppingcart() {
    var self = this;
    self.cartItems = ko.observableArray([]);
    self.grandTotal = ko.computed(function() {
        var total = 0;
        _.each(self.cartItems(), function (item) {
            total += item.subTotal(); // need parenthesis to invoke
        }
        return total; // return a value, otherwise function is void
    }

    //inital load of the data
    dataservice.loadCartItems(self.cartItems);
}

function cartItem() {
    var self = this;
    self.quantity = ko.observable(0);
    self.price = 0.00;

    self.subTotal = ko.computed(function() {
        return self.price * self.quantity();
    }
}
于 2013-11-05T17:09:15.497 に答える
1

したがって、私が正しく理解している場合、主な問題は、要素の1つが変更されたときに observableArray ミューテーションをトリガーする必要があることです。それは可能ですが、それがベストプラクティスかどうかはわかりません。代替実装については、これを参照してください: Observable notify parent ObservableArray

このフィドルのソリューション例では、手動で valueHasMutated を呼び出します: http://jsfiddle.net/F6D6U/6/

html:

<ul data-bind='foreach: cartItems'>
    <!--other stuff here -->
    <input type='text' data-bind="value: quantity, valueUpdate: 'afterkeydown'"/>
     * <span data-bind="text:price"></span>
    = <span data-bind="text:subTotal"></span>
    <br />
</ul>

<span data-bind='text: grandTotal'></span>

js:

function cartItem(q, p, a) {
    var self = this;
    self.quantity = ko.observable(q);
    self.price = p;
    self.parentArray = a;

    self.subTotal = ko.computed(function() {        
        var subtotal =  parseFloat(self.price,10) * parseFloat(self.quantity(),10);
        self.parentArray.valueHasMutated();
        return subtotal;
    },self);
}


function shoppingcart() {
    var self = this;
    self.cartItems = ko.observableArray();
    self.cartItems([
        new cartItem(10,100, self.cartItems),
        new cartItem(1,3, self.cartItems),
    ]);
    self.grandTotal = ko.computed(function() {
        var total = 0;
        ko.utils.arrayForEach(self.cartItems(), function (item) {
            total += item.subTotal();
        });
        return total;
    }, self);

    //inital load of the data
    //dataservice.loadCartItems(self.cartItems);
}

        ko.applyBindings(new shoppingcart())
于 2013-11-05T17:09:55.153 に答える