通过映射插件

时间:2015-08-31 13:56:09

标签: knockout.js typescript knockout-mapping-plugin

ViewModel从$(document).ready(..)

中的JSON初始化和映射
$(document).ready(function ()
{
    viewmodel = new Order();
    var data = { json data };
    ko.mapping.fromJSON(data, {}, viewmodel);
    ko.applyBindings(viewmodel);
});

class Order
{
    ID: KnockoutObservable<number>;
    InvoiceAddress: KnockoutObservable<Address>;
    constructor()
    {
        this.ID = ko.observable(0);
        this.InvoiceAddress= ko.observable(new Address());
        this.InvoideAddress.subscribe(function(newvalue) { console.log(newvalue)}, this);
    }
}

其他类型InvoiceAddress的{​​{1}}个Address可以是null 当用户创建或删除InvoiceAddress时,将发送$ajax请求并返回包含整个viewmodel的更新数据的新JSON对象。 接收到的数据映射到viewmodel的同一个实例

ko.mapping.fromJSON(data, {}, viewmodel);

如果InvoiceAddress的状态从null更改为现有对象,则InvoiceAddress的绑定将停止工作。

<input data-bind="value: InvoiceAddress().StreetName">

问题:在重新映射&#34;?

之后是否可以保持绑定工作

更新:&#34;停止工作&#34; - &GT; &#34; InvoiceAddress&#34;中属性的订阅者&#34; InvoiceAddress&#34;变为null并重新映射回正常对象

2 个答案:

答案 0 :(得分:3)

不要这样做。

<input data-bind="value: InvoiceAddress().StreetName">

这样做:

<div data-bind="with: InvoiceAddress">
    <input data-bind="value: StreetName">
</div>

比较

ko.applyBindings({
    InvoiceAddress: ko.observable({StreetName: "Invoice Street"}),
    ShippingAddress: ko.observable(null),
    addShipping: function () { this.ShippingAddress({StreetName: "Shipping Street"}); },
    removeShipping: function () { this.ShippingAddress(null); }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<b>Invoice Address</b>
<div data-bind="with: InvoiceAddress">
    <input data-bind="value: StreetName">
</div>

<b>Shipping Address</b>
<div data-bind="ifnot: ShippingAddress">-</div>
<div data-bind="with: ShippingAddress">
    <input data-bind="value: StreetName">
</div>

<button data-bind="click: addShipping">Add Shipping</button>
<button data-bind="click: removeShipping">Remove Shipping</button>

使用with还可以更轻松地将整个内容转换为模板或组件。

答案 1 :(得分:1)

我接受了@ Tomalak的回答,因为他的答案让我正确地理解了Knockout的Observables是如何工作的(文档不够:) :) 但是想发布解决问题的解决方案

具体问题是订阅者在knockout.mapping插件从null映射到新对象

之后停止触发
var orderData = {"ID":2,"InvoiceAddress":null}
ko.mapping.FromJS(orderData, {}, viewmodel);
//underlying object of observable this.InvoiceAddress is null
// then user added new address
var newAddressData = {"ID":3, "StreetName":"Third"} //returned by ajax request
ko.mapping.FromJS(newAddressData, {}, this.InvoiceAddress);

之后this.InvoiceAddress内的属性订阅者停止了。

问题是因为映射插件每次都创建了属性类型的新实例,而不使用初始化订户的类型的构造函数。

解决方案:在映射

之前创建基础类型的实例
var newAddressData = {"ID":3, "StreetName":"Third"}
var tempAddress: Address = new Address();
ko.mapping.FromJS(newAddressData; {}, tempAddress);
this.InvoiceAddress(tempAddress);