Javascript 为HTML标记中的可观察对象提供初始值

Javascript 为HTML标记中的可观察对象提供初始值,javascript,data-binding,knockout.js,observable,Javascript,Data Binding,Knockout.js,Observable,我试图创建一个HtmlHelper扩展,将一些HTML输出到视图中。在这个HTML中,我连接了一些KnockoutJS绑定。我是KO的新手,所以我仍然在努力完成一些事情。无论如何,我要做的是在客户端代码上生成绑定到可观察对象的输入字段(在服务器端代码中),然后通过隐藏字段的值设置可观察对象的初始值。不幸的是,这对我不起作用。因此,我想知道是否有任何方法可以让我做到这一点(即使我必须做完全不同的事情) 我基本上是这样做的: 在我的客户端视图模型中,我有以下内容: self.dataSource =

我试图创建一个
HtmlHelper
扩展,将一些HTML输出到视图中。在这个HTML中,我连接了一些KnockoutJS绑定。我是KO的新手,所以我仍然在努力完成一些事情。无论如何,我要做的是在客户端代码上生成绑定到可观察对象的输入字段(在服务器端代码中),然后通过隐藏字段的值设置可观察对象的初始值。不幸的是,这对我不起作用。因此,我想知道是否有任何方法可以让我做到这一点(即使我必须做完全不同的事情)

我基本上是这样做的:

在我的客户端视图模型中,我有以下内容:

self.dataSource = ko.observable();
self.pageSize = ko.observable();
<input type="hidden" value="/Employee/Get" data-bind="value: dataSource" />
<input type="hidden" value="30" data-bind="value: pageSize" />
我的扩展方法输出以下内容:

self.dataSource = ko.observable();
self.pageSize = ko.observable();
<input type="hidden" value="/Employee/Get" data-bind="value: dataSource" />
<input type="hidden" value="30" data-bind="value: pageSize" />


但是当页面呈现时,当我检查元素时,我注意到输入字段的
被设置为空字符串,我认为这是因为可观察对象的声明方式。但是有没有一种方法可以覆盖这种行为或其他什么呢?

一种让代码更干净的方法是使用自定义绑定,通过使用元素的当前值初始化值绑定来包装值绑定

您甚至可以让它在您的视图模型上创建观察对象,如果它们不存在的话

绑定可能类似于:

ko.bindingHandlers.valueWithInit = {
    init: function(element, valueAccessor, allBindingsAccessor, data) {
        var property = valueAccessor(),
            value = element.value;

        //create the observable, if it doesn't exist 
        if (!ko.isWriteableObservable(data[property])) {
            data[property] = ko.observable();
        }

        data[property](value);

        ko.applyBindingsToNode(element, { value: data[property] });
    }
};
你会像这样使用它:

<input value="someValue" data-bind="valueWithInit: 'firstName'" />

请注意,属性名在引号中,这允许绑定创建它,如果它不存在,而不是从未定义的值中出错


这是一个示例:

这里有点晚了。实际上,我对RP的回答并不满意,因为它打破了敲除的声明性质。具体来说,如果使用valueWithInit定义属性,则不能在早期绑定中使用它。这是一个例子

您以同样的方式使用它,但它仍然是文档范围内的声明性文件:

<input data-bind="valueWithInit: firstName" value="Joe" />
注意
valueWithInit
只是在引擎盖下使用
initValue


查看它。

如果自定义绑定太重,那么一个简单的解决方案是从DOM初始化可观察对象

例如,给定以下HTML表单:

<form name="person">
  <input type="text" name="firstName" value="Joe" data-bind="value: firstName"/>
</form>
您可以简单地使用a并将值分配给现有的可观察对象:

ko.bindingHandlers.yourBindingName = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        viewModel.dataSource($(".dataSource").val());
        viewModel.pageSize($(".pageSize").val());
    }
};

然后,只需向输入中添加一个类或Id,并向包含它们的HTML元素中添加
data bind=“yourBindingName”

可以使用的另一种方法是使用自定义绑定,通过使用元素的当前值初始化来包装
绑定。您甚至可以让它在您的视图模型上创建可观察对象(如果不存在的话)。这是一个例子:嗯。。。现在我得到了在发出的HTML标记中显示的值,但是观察值仍然没有定义。你能在JSFIDLE中放一些东西吗?不管怎样,我已经让它工作了。这是个愚蠢的错误(和往常一样!)。你能把你的答案贴出来吗?这样我就可以接受你的答案了?感谢您的帮助,非常感谢:)事实上,如果属性名称不在引号中,它将不起作用。是的,此版本的绑定将要求名称在引号中。如果您知道您的可观察对象已经存在,那么您可以直接与它们绑定,只需在
init
函数中根据元素的值设置可观察对象的值。我在过去使用过这个,我想补充一点,通过更改行
ko.applybindingstode(元素,{value:data[property]});
ko.applybindingstoode(元素,{textInput:data[property]});
获取实时双向更新。警告:initValue绑定必须在值(或任何其他值更改)绑定之前值得一提的是isModified()将设置为true,因此如果您不希望发生这种情况,则需要在设置值后将其设置为false。例如“valueAccessor().isModified(false)”
<form name="person">
  <input type="text" name="firstName" value="Joe" data-bind="value: firstName"/>
</form>
ko.applyBindings({
  firstName: ko.observable(document.forms['person']['firstName'].value)
});
ko.bindingHandlers.yourBindingName = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        viewModel.dataSource($(".dataSource").val());
        viewModel.pageSize($(".pageSize").val());
    }
};