knockout - 减去数组中的值

时间:2012-10-17 16:09:29

标签: list knockout.js nested computed-observable

我遇到以下问题。我正在使用knockout编辑包含嵌套列表的列表,有点像淘汰网站上的Contacts Editor:

http://knockoutjs.com/examples/contactsEditor.html

在我的示例中,“设计”与上述示例中的“联系人”相关,“designDeliveries”与“电话号码”相关。

所以我在每个“设计”中都有一个名为MaxQuantity的值,每个“designDelivery”中都有一个名为Quantity的值。实际上,我想要实现的是在每个“设计”中都有另一个值,称为“剩余”,它基本上是“MaxQuantity”减去所有“designDeliveries”中与“特定”设计相关的“数量”之和”。当我添加新的“designDeliveries”并填充“数量”字段时,这当然应从该特定设计的新“剩余”值中扣除

到目前为止,我的代码如下:

var DesignsModel = function (designs) {

    var self = this;
    self.designs = ko.observableArray(ko.utils.arrayMap(designs, function (design) {
        return {    BookingDesignId: design.BookingDesignId, 
            DesignName: design.DesignName, 
            MaxQuantity: design.Quantity,
            DesignDeliveries: ko.observableArray(design.DesignDeliveries) };
    }));

    self.addDesignDelivery = function (design) {
        design.DesignDeliveries.push({
            Quantity: "",
            DepotId: ""
        });
    };

    self.removeDesignDelivery = function (designDelivery) {
        $.each(self.designs(), function () { this.DesignDeliveries.remove(designDelivery) })
    };

    self.save = function () {
        self.lastSavedJson(JSON.stringify(ko.toJS(self.designs), null, 2));
    };

    self.lastSavedJson = ko.observable("");

};

ko.applyBindings(new DesignsModel(initialData));

initialData如下所示:

[{"DesignId":"1","DesignName":"Design1","Quantity":50,"DesignDeliveries":[]},{"DesignId":"2","DesignName":"Design2","Quantity":50,"DesignDeliveries":[]},{"DesignId":"3","DesignName":"Design3","Quantity":500,"DesignDeliveries":[]}] 

和html一样:

<div data-bind="foreach: designs">

    <div>
        <span data-bind="text: DesignName"></span>
        <a href="#" data-bind="click: $root.addDesignDelivery">Add</a>
    </div>
    <div>
        <span data-bind="text: MaxQuantity"></span>
    </div>
    <div>
        <span data-bind="text: Remaining"></span>
    </div>

    <div data-bind="foreach: DesignDeliveries">
        <div>
            <input data-bind="value: Quantity" />
        </div>
        <div>  
            <a href="#" data-bind="click: $root.removeDesignDelivery">
                Delete
            </a>             
        </div>          
    </div>    
</div>

我希望这很清楚。有没有人知道如何实现这个目标?

提前致谢

1 个答案:

答案 0 :(得分:1)

我建议您将复杂的视图模型拆分为几个小视图模型。然后,要获得所需的功能,您只需添加计算剩余数量的计算:

var DesignDeliveryModel = function(quantity, depotId) {
    var self = this;

    self.Quantity = ko.observable(quantity);
    self.DepotId = depotId;
};

var DesignModel = function(bookingDesignId, designName, maxQuantity, deliveries) {
    var self = this;

    self.BookingDesignId = bookingDesignId;
    self.DesignName = designName;
    self.MaxQuantity = maxQuantity;
    self.DesignDeliveries = ko.observableArray(deliveries);

    self.Remaining = ko.computed(function() {
        var result = self.MaxQuantity;
        ko.utils.arrayForEach(self.DesignDeliveries(), function(item) {
            result = result - item.Quantity();
        });
        return result;
    });

    self.addDesignDelivery = function() {
        self.DesignDeliveries.push(new DesignDeliveryModel(0, ""));
    };

    self.removeDesignDelivery = function(designDelivery) {
        self.DesignDeliveries.remove(designDelivery);
    };
};

var DesignsModel = function(designs) {
    var self = this;

    self.designs = ko.observableArray(ko.utils.arrayMap(designs, function(design) {
        return new DesignModel(design.BookingDesignId, design.DesignName, design.Quantity, design.DesignDeliveries);

    }));

    self.save = function() {
        self.lastSavedJson(JSON.stringify(ko.toJS(self.designs), null, 2));
    };

    self.lastSavedJson = ko.observable("");
};

对html的小更新,以更改调用添加和删除功能的上下文:

<div data-bind="foreach: designs">
    <div>
        <span data-bind="text: DesignName"></span>
        <a href="#" data-bind="click: addDesignDelivery">Add</a>
    </div>
    <div>
        <span data-bind="text: MaxQuantity"></span>
    </div>
    <div>
        <span data-bind="text: Remaining"></span>
    </div>

    <div data-bind="foreach: DesignDeliveries">
        <div>
            <input data-bind="value: Quantity" />
        </div>
        <div>  
            <a href="#" data-bind="click: $parent.removeDesignDelivery">
                Delete
            </a>             
        </div>          
    </div>    
</div>

这是工作小提琴:http://jsfiddle.net/vyshniakov/7JUGE/