简体   繁体   中英

Late observable-array binding in KnockoutJS

My MVC razor view renders this markup:

function existingNamingsViewModel() {
            var self = this;
            var initialData = @Html.Raw(new JavaScriptSerializer().Serialize(Model));
            self.ExistingNamings = ko.observableArray(initialData);
        }
        ko.applyBindings(new existingNamingsViewModel(), document.getElementById("namings-control"));

Into a correct JS-serialized code, with initialData variable being initialized as:

var initialData = [{"TypeName":"Orders","NameBlocks":["{intInc_G}","/","{intInc_D}","/02/-","{yy}"],"ParamBlocks":["2296","","1","",""]}];

The resulting html, after the ko bindings are applied, takes the form of an editable grid: 在此处输入图片说明

I need knockoutJS to automatically be able to update the view model whenever user changes data in those input fields. But since the view model was initialize from simple JSON object, NameBlocks and ParamBlocks are not ko.observableArray . I need them to be. How do I achieve this?

PS One idea is to do a more complex initialization where razor serializes only Name / ParamBlocks arrays, and ExistingNamings array is populated via javascript code manually, creating a custom Naming class object that has Name / ParamBlocks wrapped into ko.observableArray . But is this the only way?

There's a mapping plug-in available that should do the trick for you, though you may need to change the way the data is delivered.

The mapping plug-in provides a function that maps a JSON object to a view model:

var viewModel = ko.mapping.fromJS(data);

Note though, in the documentation (linked to above), all properties within JSON objects are named.

The initialData you provided in your example contains arrays that are simply collections of values, rather than collections of named values.

Also, initialData is an array containing a single object. If this scenario is always going to expect a single object, then this solution is easier.

Let's say that you're able to deliver initialData in the following format:

var initialData = {
    "TypeName":"Orders",
    "NameBlocks": [
        {"block":"{intInc_G}"},
        {"block":"/"},
        {"block":"{intInc_D}"},
        {"block":"/02/-"},
        {"block":"{yy}"}
    ],
    "ParamBlocks":[
        {"block":"2296"},
        {"block":""},
        {"block":"1"},
        {"block":""},
        {"block":""}
    ]
};

Then creating the view model would be as simple as the following:

var viewModel = ko.mapping.fromJS(initialData);

$(function() {
   ko.applyBindings(viewModel); 
});

Here's a fiddle I set up so you can see this in action: http://jsfiddle.net/jimmym715/qUjLQ/

Hopefully, your solution will be as simple as a few data format changes and the use of the mapping plug-in.

Regardless, the mapping plug-in should send you in the right direction.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM