KnockoutJS模型绑定之前的MVC模型绑定

时间:2012-06-21 17:50:41

标签: asp.net-mvc razor knockout.js

因此,如果你的Controller Action返回一个带有预先填充值的模型,你如何让KnockoutJS知道它们?

E.g:

@Html.TextBoxFor(m => m.Title, new { data_bind="value: title"} )

但是,在绑定knockout.js ViewModel的$(document).ready()上,此值尚未填充:

$(document).ready({
  var viewModel = {
    title: ko.observable($("#Title").val()) // too early for this?!
  }

  ko.applyBindings(viewModel);​
});

你如何让KnockoutJS与MVC的模型绑定一起工作? 我找到的一个解决方法是在我的Razor View中设置JavaScript变量,如下所示:

<script>
  var strTitle = '@Model.Title';
</script>

而不是在Knockout模型绑定中使用它。这有效,但我讨厌它。如果您的表单有数百个字段怎么办?您不希望页面中包含任意数量的JavaScript变量。 我错过了明显的吗?

3 个答案:

答案 0 :(得分:3)

这似乎与this question类似。通常,您可以通过在脚本中将@Model转换为JSON来设置视图模型:

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

您还可以创建自己的绑定处理程序,该处理程序最初将根据控件值加载视图模型。这个新的myvalue处理程序基本上调用现有的value处理程序,除了它从初始控制值更新视图模型

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);
        modelValue(elementValue); // simplified next line, writeValueToProperty isn't exported
        //ko.jsonExpressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'value', elementValue, /* checkIfDifferent: */ true);
    },
    'update': function (element, valueAccessor) {
        // call existing value update code
        ko.bindingHandlers['value'].update(element, valueAccessor);
    }
};

然后当你调用ko.applyBindings时,你的observable最初将根据控件的值设置:

<input type="text" data-bind="myvalue: Title" value="This Title will be used" />
<input type="text" data-bind="value: Title" value="This will not be used" />
<!-- MVC -->
@Html.TextBoxFor(m => m.Title, new { data_bind="myvalue: Title"} )

SAMPLE FIDDLE

答案 1 :(得分:2)

如何使用JSON.NET或类似方法将整个页面模型序列化为json。然后,您的页面将通过非js用户的普通剃刀视图绑定进行填充。然后您的页面脚本可以是:

<script>
    ko.applyBindings(@Html.ToJSON(Model));
</script>

或者,如果您有一个类型化的viewModel

<script>
    var viewModel = new MyViewModel(@Html.ToJSON(Model));
    ko.applyBindings(viewModel);
</script>

将客户端和实际视图模型结构相同是有意义的,因此不需要对json形状进行操作。

修改

toJSON助手的示例。

public static MvcHtmlString ToJson(this HtmlHelper html, object obj)
{
  JavaScriptSerializer serializer = new JavaScriptSerializer();
  return MvcHtmlString.Create(serializer.Serialize(obj));
}

希望这有帮助。

答案 2 :(得分:2)

因为我没有给Jason Goemaat answer添加评论50分的声​​誉,所以我决定在此处添加我的评论作为答案。

所有学分归Jason Goemaat所有。

我无法让代码对我有用。所以我不得不做一个小改动。

        ko.bindingHandlers['myvalue'] = {
    'init': function (element, valueAccessor, allBindingsAccessor) {
        //get initial state of the element            
        var modelValue = valueAccessor();
        var elementValue = ko.selectExtensions.readValue(element);

        // call existing value init code
        ko.bindingHandlers['value'].init(element, valueAccessor, allBindingsAccessor);

        //Save initial state
        modelValue(elementValue);
    },
    'update': function (element, valueAccessor) {
        // call existing value update code
        ko.bindingHandlers['value'].update(element, valueAccessor);
    }
};

如果我在顶部有这条线,

// call existing value init code
ko.bindingHandlers['value'].init(element, valueAccessor, allBindingsAccessor);

它正在删除元素的原始状态。所以无论我在输入字段中有什么价值,它都被删除了。

在模型中我有这个:

//publishing comment
self.publishingComment = ko.observable();

我的MVC看起来像这样

@Html.TextBoxFor(model => model.Comment, new { data_bind = "myvalue: publishingComment" })