3

Working with KnockOut - I'm trying to build the basics of a master detail/items app before adding to MVC .Net code.

All I want to do is have a simple item, price, tax - and for a computed column to show the amount including tax for each item:

The client side KnockOut viewmodel is:

var GiftModel = function(gifts) {
var self = this;
self.gifts = ko.observableArray(gifts);

 self.formattedPrice = ko.computed(function() {
    var pricet = self.gifts().price;
    return pricet ? "$" + pricet.toFixed(2) * (1 + self.gifts().tax : "None"; 

});    

self.addGift = function() {
    self.gifts.push({
        name: "",
        price: "",
        tax:0
    });
};

self.removeGift = function(gift) {
    self.gifts.remove(gift);
};

self.save = function(form) {
    alert("Could now transmit to server: " + ko.utils.stringifyJson(self.gifts));
    // To actually transmit to server as a regular form post, write this: ko.utils.postJson($("form")[0], self.gifts);
};
};

var viewModel = new GiftModel([
{ name: "Tall Hat", price: "39.95", tax:17.5},
{ name: "Long Cloak", price: "120.00", tax:20}
]);
ko.applyBindings(viewModel);

// Activate jQuery Validation
$("form").validate({ submitHandler: viewModel.save });

The table markup is:

<table data-bind='visible: gifts().length > 0'>
        <thead>
            <tr>
                <th>Gift name</th>
                <th>Price</th>
                <th>Tax</th>
                <th />
            </tr>
        </thead>
        <tbody data-bind='foreach: gifts'>
            <tr>
                <td><input class='required' data-bind='value: name, uniqueName: true' /></td>
                <td><input class='required number' data-bind='value: price, uniqueName: true' /></td>
                 <td><input class='required number' data-bind='value: tax, uniqueName: true' /></td>
               <td data-bind='text: formattedPrice'></td>
                <td><a href='#' data-bind='click: $root.removeGift'>Delete</a></td>

            </tr>
        </tbody>
    </table>

    <button data-bind='click: addGift'>Add Gift</button>
    <button data-bind='enable: gifts().length > 0' type='submit'>Submit</button>

It's stalling as the formattedPrice function doesnt appear to be working.

I've got it in a jsfiddle here: http://jsfiddle.net/marktait/TR6Sy/ - would anyone be able to help me get over this seemingly simple hurdle?

Thank you,

Mark

4

3 回答 3

4

问题是您在循环礼物列表时调用了 comouted 函数。但是,计算方法不适用于给定的礼物,而是适用于所有礼物。你有两个选择:

要么你让每个礼物对象都是一个使用这个计算方法的对象(就像用户布兰登建议的那样),或者你只是将它转换为一个以礼物作为参数的普通函数,如下所示:

self.getFormattedPrice = function(price, tax) {
    var val = price ? "$" + parseFloat(price).toFixed(2) * (1 + tax) : "None";
    return val;
};    

然后,你这样称呼它:

<td data-bind='text: $parent.getFormattedPrice(price, tax)'></td>

我已经更新了你的小提琴

于 2013-05-14T13:29:58.603 回答
2

self.gifts()是一个数组。但是在您的计算中,您试图将其用作单个值。那是行不通的。您需要将其作为计算属性添加到数组中的每个项目:

var addFormattedPrice = function (gift) {
   gift.formattedPrice = ko.computed(function () {
       var pricet = gift.price;
       return pricet ? "$" + pricet.toFixed(2) * (1 + gift.tax : "None"; 
   });
};

ko.utils.arrayForEach(self.gifts(), addFormattedPrice);

self.addGift = function() {
    var gift = {
        name: "",
        price: "",
        tax:0
    };
    addFormattedPrice(gift);
    self.gifts.push(gift);
};
于 2013-05-14T13:22:54.720 回答
0

看起来您只是缺少一个右括号-

return pricet ? "$" + pricet.toFixed(2) * (1 + self.gifts().tax : "None"; 

应该

return pricet ? "$" + pricet.toFixed(2) * (1 + self.gifts().tax) : "None"; 
于 2013-05-14T13:14:30.807 回答