knockout.js load form into viewModel

2019-05-27 11:28发布

问题:

I'm currently successfully using knockout.js to handle all of my data-binding in my application. However, on each page load, in my document.ready I'm doing an initial asnychronous data load like this:

$(document).ready() {
  getData()
});

However, is it possible to instead, load the data into a form (using ASP.NET MVC2) and then reverse load the data into the view model based on the data-bind tags?

I feel like this doesn't work, I just want to confirm that I'm not doing anything improperly.

回答1:

The 'value' binding initially sets the value of the element to the one in your view model, so no. However, you could probably duplicate the code for the 'value' binding into your own handler that does initially set the model values from the values on the controls. Download the debug version of knockout, and look for ko.bindingHandlers['value'] = { on line 2182. Copy this binding handler declaration and change 'value' to something else, then add a call to valueUpdateHandler() at the end of init:

ko.bindingHandlers['myvalue'] = {
    'init': function (element, valueAccessor, allBindingsAccessor) {
        // skipping code
        valueUpdateHandler(); // update model with control values
    },
    'update': function (element, valueAccessor) {
        // skipping code
    }
};

Now when you use the myvalue binding, your model will be updated with the control values when initially bound:

<input type="text" data-bind="myvalue: name"></input>

Alternatively you could call the original values instead of copying all the code, and just add the code from valueUpdateHandler after the init:

ko.bindingHandlers['myvalue'] = {
    'init': function (element, valueAccessor, allBindingsAccessor) {
        // call existing value init code
        ko.bindingHandlers['value'].init(element, valueAccessor, allBindingsAccessor);

        // valueUpdateHandler() code
        var modelValue = valueAccessor();
        var elementValue = ko.selectExtensions.readValue(element);
        ko.jsonExpressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'value', elementValue, /* checkIfDifferent: */ true);
    },
    'update': function (element, valueAccessor) {
        // call existing value update code
        ko.bindingHandlers['value'].update(element, valueAccessor);
    }
};

If you don't want to use AJAX, you can always get the values into javascript by serializing your model as JSON (razor syntax):

<script type="text/javascript">
var model = @(new HtmlString(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model)));
</script>


回答2:

There's a working example here (not mine) with several different ways to achieve this:

http://jsfiddle.net/rniemeyer/5Z2SC/