如何在不使用映射的情况下更新ViewModel

时间:2015-01-21 20:30:13

标签: javascript c# jquery knockout.js

我有一个淘汰ViewModel,它有一些observable,一些可观察的可观察数组。

var FulfillRequistionRequestModel = function (data) {
    data = data || {}; var self = {};

    self.RequisitionId = ko.observable(data.RequisitionId || null);
    self.FulfillItemList    = ko.observableArray(
        ko.utils.arrayMap(data.FulfillItemList, function (item_list) { return new FulfillItemModel(item_list); })
    );
    self.NumberOfItems = ko.computed(function () { return self.FulfillItemList().length; });

    //add-remove FullfillItem in FulfillItemList (this is per line number)
    self.removeItemFromList = function (fulfill_item) { self.FulfillItemList.remove(fulfill_item); };
    self.addItemToList = function () { self.FulfillItemList.push(new FulfillItemModel()); };

    return self;
};

var FulfillItemModel = function (data) {
    data = data || {}; var self = {};

    self.BoxNumber      = ko.observable(data.BoxNumber                  || null);
    self.LineNumber     = ko.observable(data.LineNumber                 || null);
    self.SourceBin      = ko.observable(new BinModel(data.SourceBin)    || null);
    self.ItemDetailList = ko.observableArray(
        ko.utils.arrayMap(data.ItemDetailList, function (item_list) { return new ItemDetailModel(item_list); })
    );
    self.NumberOfItems = ko.computed(function () {return self.ItemDetailList().length;});

    //add-remove something from ItemDetailList (ItemDetail)
    self.removeItemFromList = function (item) { self.ItemDetailList.remove(item); };
    self.addItemToList = function () { self.ItemDetailList.push(new ItemDetailModel()); };

    return self;
};
var ItemDetailModel = function(data) {
    data = data || {}; var self = {};

    self.Part           = ko.observable(data.Part           || null);
    self.Owner          = ko.observable(data.Owner          || null);
    self.Condition      = ko.observable(data.Condition      || null);
    self.Bcn            = ko.observable(data.Bcn            || null);
    self.SerialNumber   = ko.observable(data.SerialNumber   || null);
    self.Quantity       = ko.observable(data.Quantity       || null);

    return self;
};

var myModel = new FulfillRequistionRequestModel(thing);
ko.applyBindings(myModel);

你明白了。我有一个ViewModel,它有一些observable,然后是一个observablearray,由一组observables(ItemModel)组成。

以下是它正在消费的JSON样本:

var thing = {
    RequisitionId: 55,
    FulfillItemList: [
        {
            BoxNumber: 555,
            LineNumber: 001,
            SourceBin: { Location: "Jason", Warehouse: "AMERICA" },
            ItemDetailList: [
                { Part: "999-JASONTEST-111", Condition: "OLD" },
                { Part: "999-JASONTEST-115", Quantity: 55 }
            ]

        },
        {
            BoxNumber: 444,
            LineNumber: 002,
            SourceBin: { Location: "Jason", Warehouse: "CANADA" },
            ItemDetailList: [
                { Part: "999-JASONTEST-221", Condition: "NEW" },
                { Part: "999-JASONTEST-225", Bcn: "ABC123", Condition:"BUSTED", Quantity: 23 },
                { Part: "999-JASONTEST-228", Quantity: 55 }
            ]

        }
    ]
};

想象一下这是一个"命令"。有人点击订单ID,它会加载相关信息。我想要它,所以如果他们点击另一个订单ID - 视图模型将使用该信息更新(来自AJAX调用的新JSON)。

无处不在我看到,说使用ko.mapping.fromJS(newJSON, mapping, viewModel);格式 - 但是我咬了一下子弹,而且这次我没有用ko.mapping映射我的ViewModel,我花了时间来构建它因此,我可以真正展示自己的肌肉,而ko.mapping似乎无法在我手工制作的MVVM上工作。

所以 - 让我说我得到一个新的顶级数据 - 如何刷新myModel以便它全部正常工作?

我甚至试图设置myModel = {}myModel = new FulfillRequisitionRequestModel({});只是为了看看我是否可以将元素/页面清零 - 但这似乎打破了.applyBindings,因为页面停止响应 - 不再连接。

所以 - 我有myModel - 而且效果很好。这是一个"命令"列出了该订单中的东西(产品,说) - 以及客户信息。如何将新订单加载到模型中?

真的不想拆除并重置"每个子观察。我想像ko.mapping那样刷新它 - 坦率地说,如果我必须走过去打扫房子 - 那么重点是什么?回到ko.mapping,让它处理所有这些。

所以 - 使用我精心构建的视图模型 - 如何使用来自AJAX / REST(它的JSON)的一整套新数据来更新它 - 就像ko.mapping.fromJS那样?

1 个答案:

答案 0 :(得分:0)

这真是令人沮丧,RP Niemeyer led me on the right path使用ko.utils.extend来扩展外部刷新。这对我不起作用,这可能是由于我在每个对象中引用了selfthisreturn self

基本上,我将FulfillRequistionRequestModel(顶级狗)改为:

var FulfillRequistionRequestModel = function (data) {
    data = data || {}; var self = {};

    self.RequisitionId      = ko.observable();      //neutered
    self.FulfillItemList    = ko.observableArray(); //neutered

    self.NumberOfItems      = ko.computed(function () { return self.FulfillItemList().length; });

    //add-remove FullfillItem in FulfillItemList (this is per line number)
    self.removeItemFromList = function (fulfill_item) { self.FulfillItemList.remove(fulfill_item); };
    self.addItemToList      = function () { self.FulfillItemList.push(new FulfillItemModel()); };


    //allow self updates
    self.update = function (data) {
        data = data || {};
        self.FulfillItemList.removeAll(); self.RequisitionId(data.RequisitionId || null);
        if (data.FulfillItemList) {
            $.each(data.FulfillItemList, function (i, item) {
                self.FulfillItemList.push(new FulfillItemModel(item));
            });
        }
    }; if (data) { self.update(data); } //this handles first-construction (.applyBinding)

    return self;
};

你会注意到这一点,我将两个主要的可观察属性设置为空(RequisitionIdFulfillItemList) - 然后创建一个self.update函数将这些字段重置为content或null,具体取决于传入的内容。我确信可能比使用$.each推送更优雅。也许ko.utils.arrayMap或其他一些,但这有效。

<强> TLDR: 我在viewmodel中创建了一个更新例程。这并不完美,因为它现在有了它ko.mapping.toJS,将它发送回C#/ REST-API,但这也很好,因为它消耗它的方式,它忽略了任何额外的东西。

public IHttpActionResult testloadpart(FulfillRequisitionRequest incoming) {
//do stuff
//incoming.update does not exist.
//incoming.NumberOfItems does not exist.
//incoming.RequisitionId DOES exist

}


public partial class FulfillRequisitionRequest {

    [XmlElementAttribute(Order = 0)]
    public long RequisitionId { get; set; }
    [XmlArrayAttribute(Order = 1)]
    [XmlArrayItemAttribute("FulfillItem", IsNullable = false)]
    public List<fulfillItem> FulfillItemList { get; set; }

    public FulfillRequisitionRequest() {
        FulfillItemList = new List<fulfillItem>();
    }
}