模板“data”绑定提供值而不是可观察的值

时间:2013-12-28 12:46:20

标签: javascript templates knockout.js

我正在尝试使用模板绑定及其绑定到observable的“数据”。但是,模板内控件的$ data正在接收“可观察值”(而不是可观察值本身)。

因为我得到了值而不是可观察量,所以如果我使用模板,我就无法设置双向绑定。如果我设置了直接绑定,则相同的代码可以正常工作。

这是一个突出我问题的jsfiddle:http://jsfiddle.net/8cDLw/

HTML

Working Example: <div id="workingExample">
    <select data-bind="options: _.range(0,24), hour: MyDate"></select>
    Selected Value is: <span data-bind="text: MyDate" />
</div>

<br/>Non-Working Example: <div id="notWorkingExample" data-bind="template: { name: 'hour-template', data: MyDate }"></div>

<script type="text/html" id="hour-template">
    <select data-bind="options: _.range(0,24), hour: $data" />
    Selected Value is: <span data-bind="text: $data" />
</script>

的JavaScript

ko.bindingHandlers.hour = {
    init: function(element, valueAccessor, addBindingsAccessor) {
        var $el = $(element);
        var curDate = valueAccessor();

        if (!ko.isObservable(curDate)) {
            console.log("Failure: Input Not an observable object. Data type found: " + typeof curDate + ", value: " + curDate);
        }
        $el.val(ko.utils.unwrapObservable(curDate).getHours());

        ko.utils.registerEventHandler(element, "change", function() {
            var currentDate = valueAccessor();
            var hour = $el.val();
            var date = ko.utils.unwrapObservable(currentDate);
            date.setHours(hour);

            if (ko.isObservable(currentDate))
                currentDate(date);
            else
                console.log("Cannot update value. Input not an observable.");
        });
    }
};

var viewModel = function()
{
    this.MyDate = ko.observable(new Date("2013-11-08T06:27:00.000Z"));
}

ko.applyBindings(new viewModel(), document.getElementById("notWorkingExample"));
ko.applyBindings(new viewModel(), document.getElementById("workingExample"));

注意声明的2个div:“workingExample”和“notWorkingExample”被绑定到同一个viewModel的新实例(其中包含一个observable:一个硬编码的日期。)

workingExample绑定是一个接收可观察的常规自定义绑定...在这种情况下,操纵日期的“小时”部分(有效...即如果我更改下拉值,它会更新日期时间的“小时”字段。)

在NotWorkingExample中,我将observable作为“数据”传递给模板(然后尝试使用与workingExample相同的可观察结果。)

我在这里显然遗漏了一些东西,因为从我的角度来看,NotWorkingExample应该在功能上等同于workingExample ...唯一的区别是不是直接绑定值,而是通过模板传递值 - &gt; “数据”绑定。

这里的想法是在模板中使用另一个<select>来进行双向“分钟”绑定等,以便使用模板构建自定义控件。

你能指出我做错了吗?

修改

看看我的例子,意识到我不必要地使事情变得复杂:

这是一个更简单的jsFiddle:http://jsfiddle.net/3kkC5/

对这两种实现的想法?感谢。

1 个答案:

答案 0 :(得分:1)

当对模板使用data选项时,KO会自动为您解包并获取依赖关系,因此当可观察数据发生更改时模板会更新。

KO 3.0确实有一个新的$rawData上下文变量,用于在KO将其作为创建新上下文的一部分展开的情况下为您提供原始可观察对象。但是,在这种情况下,template绑定已经解开了data选项本身。这似乎是我们可以在KO中改进的情况,因为理想情况下$rawData将是正确的选择。

因此,在您的特定情况下,您可以选择将您的observable作为属性传递对象文字,如:

template: { name: 'mytmpl', data: { myDate: MyDate } }

然后,您可以使用myDate或任何您想要称之为属性的内容来引用observable。

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

正如旁注,在你的小提琴中你有一些<span /><select />的案例。这可能会导致绑定问题,因为它们不是HTML5中的自动关闭标记。您需要使用<span></span><select></select>