从HTML标记中为observable提供初始值

Kas*_*sem 24 javascript data-binding observable knockout.js

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

这是我基本上在做的事情:

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

self.dataSource = ko.observable();
self.pageSize = ko.observable();
Run Code Online (Sandbox Code Playgroud)

我的扩展方法输出如下:

<input type="hidden" value="/Employee/Get" data-bind="value: dataSource" />
<input type="hidden" value="30" data-bind="value: pageSize" />
Run Code Online (Sandbox Code Playgroud)

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

Joe*_*Joe 23

这里有点晚了.我对RP的回答并不满意,因为它打破了Knockout的声明性质.具体来说,如果使用valueWithInit定义属性,则不能在早期绑定中使用它.这是他演示的jsfiddle的一个分支.

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

<input data-bind="valueWithInit: firstName" value="Joe" />
Run Code Online (Sandbox Code Playgroud)

扩展这个想法,你也可以使用它来分离初始化和绑定:

<input data-bind="initValue: lastName, value: lastName" value="Smith" />
Run Code Online (Sandbox Code Playgroud)

这有点多余,但在使用插件而不是内置绑定时变得有用:

<input data-bind="initValue: lastName, myPlugin: lastName" value="Smith" />
Run Code Online (Sandbox Code Playgroud)

扩展一点,我还需要一种初始化复选框的方法:

<input type="checkbox" data-bind="checkedWithInit: isEmployed" checked />
Run Code Online (Sandbox Code Playgroud)

以下是处理程序:

ko.bindingHandlers.initValue = {
    init: function(element, valueAccessor) {
        var value = valueAccessor();
        if (!ko.isWriteableObservable(value)) {
            throw new Error('Knockout "initValue" binding expects an observable.');
        }
        value(element.value);
    }
};

ko.bindingHandlers.initChecked = {
    init: function(element, valueAccessor) {
        var value = valueAccessor();
        if (!ko.isWriteableObservable(value)) {
            throw new Error('Knockout "initChecked" binding expects an observable.');
        }
        value(element.checked);
    }
};

ko.bindingHandlers.valueWithInit = {
    init: function(element, valueAccessor, allBindings, data, context) {
        ko.applyBindingsToNode(element, { initValue: valueAccessor() }, context);
        ko.applyBindingsToNode(element, { value: valueAccessor() }, context);
    }
};

ko.bindingHandlers.checkedWithInit = {
    init: function(element, valueAccessor, allBindings, data, context) {
        ko.applyBindingsToNode(element, { initChecked: valueAccessor() }, context);
        ko.applyBindingsToNode(element, { checked: valueAccessor() }, context);
    }
};
Run Code Online (Sandbox Code Playgroud)

注意valueWithInit只需initValue在引擎盖下使用.

在jsfiddle上看到它.


RP *_*yer 21

可以用来保持代码更清晰的一种替代方法是使用自定义绑定来包装值绑定,方法是使用元素的当前值初始化它.

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

绑定可能看起来像:

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] });
    }
};
Run Code Online (Sandbox Code Playgroud)

您会像以下一样使用它:

<input value="someValue" data-bind="valueWithInit: 'firstName'" />
Run Code Online (Sandbox Code Playgroud)

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

以下是一个示例:http://jsfiddle.net/rniemeyer/BnDh6

  • 是的,这个版本的绑定需要名称在引号中.如果你知道你的observable已经存在,那么你可以直接绑定它们,并简单地从元素的值设置`init`函数中的observable值. (2认同)