1

所以如果你的控制器动作返回一个带有预填充值的模型,你如何让 KnockoutJS 知道它们呢?

例如:

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

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

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

  ko.applyBindings(viewModel);​
});

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

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

而不是在 Knockout 模型绑定中使用它。这行得通,但我讨厌它。如果您的表单有数百个字段怎么办?您不希望页面中有那么多 JavaScript 变量。我在这里错过了显而易见的事情吗?

4

3 回答 3

3

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

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

您还可以创建自己的绑定处理程序,该处理程序最初将根据控制值加载视图模型。这个新myvalue的处理程序基本上调用现有的value处理程序,除了它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);
        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"} )

样品小提琴

于 2012-06-21T20:51:41.307 回答
2

使用 JSON.NET 或类似方法将整个页面模型简单地序列化为 json 怎么样。然后,您的页面将通过非 js 用户的普通 razor 视图绑定填充。然后你的页面脚本可以是这样的:

<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));
}

希望这可以帮助。

于 2012-06-21T18:07:55.957 回答
2

因为我没有 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" })
于 2015-06-04T13:46:04.807 回答