使用knockout.js更新项目数组

时间:2013-07-10 09:37:29

标签: knockout.js

我很擅长使用KnockoutJS作为框架,我(显然)遇到了一个我不能(或者更有可能,不够熟练)找到的问题。

我有这个产品组,每个产品组都包含一系列产品。现在,我设法显示产品组列表和所有产品列表,没有太大问题。我希望增加产品数量,当用户左键单击包含产品的div并在用户右键单击包含产品的div时减少产品数量。

我已正确设置事件处理程序,因为它们被解雇并处理没有任何问题,数量也发生了变化,但我似乎无法在页面上反映出来。

标记:

<div class="viewProductGroup" data-bind="with: productGroupData">
    <h2 data-bind="text: Title"></h2>
    <div class="stickies" data-bind="foreach: Products">
        <div data-bind="click: $root.addProduct, 
                        event: { contextmenu: $root.removeProduct }">
            <span data-bind="text: Title"></span><br />(<span data-bind="text: Quantity"></span>)</div>
    </div>
</div>

摘录自JS:

function StickyExViewModel() {
    var self = this;

    self.productGroupData = ko.observable();

    // Behaviors
    self.addProduct = function (item) {
        item.Quantity++;
    }
    self.removeProduct = function (item) {
        item.Quantity--;
    }
}

ko.applyBindings(new StickyExViewModel());

现在,我确信我不了解某些内容或错过了一些布线。你能帮忙吗?

修改

以下是从WCF服务获得的JSON:

{"d":
    {"__type":"ProductGroup:#Stickyex.Services",
     "Created":"\/Date(1373407200000+0200)\/",
     "ID":1,
     "Products":[
        {"__type":"Product:#Stickyex.Services","Code":"0","ID":0,"Quantity":0,"Title":"0"},
        {"__type":"Product:#Stickyex.Services","Code":"1","ID":1,"Quantity":1,"Title":"1"},
        {"__type":"Product:#Stickyex.Services","Code":"2","ID":2,"Quantity":2,"Title":"2"}],
     "Title":"ProductGroup 1"}
}

获取JSON数据的代码(在StickyExViewModel中):

self.goToProductGroup = function(productGroup) {
    $.get(serviceUrl, { ixProductGroup: productGroup.ID }, function (data) {
        self.productGroupData(data.d);
    });
}

4 个答案:

答案 0 :(得分:1)

我猜那个item.Quantity是可观察的,所以你不能使用递增和递减。每个observable都是一个函数,因此您必须使用()来获取或设置值:

// Behaviors
self.addProduct = function (item) {
    item.Quantity(item.Quantity() + 1);
}
self.removeProduct = function (item) {
    item.Quantity(item.Quantity() - 1);
}

答案 1 :(得分:1)

数量属性需要是可以忽略的。 所以在StickyExViewModel中你可以这样做:

function StickyExViewModel() {
    var self = this;

    self.productGroupData = ko.observable();

    // Behaviors
    self.addProduct = function (item) {
        item.Quantity( item.Quantity()++);
    }
    self.removeProduct = function (item) {
        item.Quantity( item.Quantity()--);
    }
}

通过将数量转换为可观察量,您的Gui将在您更改属性后立即刷新。

答案 2 :(得分:1)

我认为您需要对将productGroupData转换为可观察对象的方式进行一些修改。

首先:productGroupData应为observableArray而不是observable,因为它实际上是一个数组。
self.productGroupData = ko.observableArray([]);

其次,要将您的JSON字符串转换为observableArray,您可以利用KnockoutJS mapping plugin。这将使您的编码更好。因此,您可以使用它将JSON转换为observableArray

ko.mapping.fromJS(yourJS_Object, {}, self.productGroupData);//in case you have JS object

OR

ko.mapping.fromJSSON(yourJSON_String, {}, self.productGroupData);//in case you have JSON string.

现在请注意,您productGroupData的所有属性或对象都是可观察的,因此要访问它们,您需要使用()

答案 3 :(得分:0)

感谢所有试图并成功帮助我的人,我找到了最终的解决方案。为了更新Quantity,我不应该直接绑定到JSON对象,而是在JS中创建表示JSON对象模型的类。

function Product(item) {
    this.ID = item.ID;
    this.Title = item.Title;
    this.Quantity = ko.observable(item.Quantity);
}

function ProductGroup(data) {
    var self = this;
    this.ID = data.ID;
    this.Title = data.Title;
    this.Products = [];
    for (var i = 0; i < data.Products.length; i++) {
        self.Products.push(new Product(data.Products[i]));
    }
}

我获得JSON的部分改为:

self.goToProductGroup = function(productGroup) {
    $.get(serviceUrl, { ixProductGroup: productGroup.ID }, function (data) {
        self.productGroupData($.map(data, function (pg) {
            return new ProductGroup(pg);
        }));
    });
}