【问题标题】:Template "data" binding provides value instead of an observable模板“数据”绑定提供值而不是可观察的
【发布时间】:2014-01-15 20:56:54
【问题描述】:

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

因为我得到的是值,而不是 observable,所以如果我使用模板,我将无法设置 2 向绑定。如果我设置直接绑定,相同的代码可以正常工作。

这是一个突出我的问题的 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 的新实例(其中包含一个可观察的:硬编码日期。)

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

在 NotWorkingExample 中,我将 observable 作为“数据”传递给模板(然后尝试使用与 workingExample 相同的绑定来使用该 observable。)

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

这里的想法是在模板中添加另一个 &lt;select&gt; 以进行 2 向“分钟”绑定等,从而实质上使用模板构建自定义控件。

你能指出我做错了什么吗?

编辑:

看了我的例子,意识到我把事情复杂化了:

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

对这两种实现有什么想法吗?谢谢。

【问题讨论】:

    标签: javascript templates knockout.js


    【解决方案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/

    顺便说一句,在您的小提琴中,您有一些 &lt;span /&gt;&lt;select /&gt; 的案例。这可能会导致您的绑定出现问题,因为它们在 HTML5 中不是自闭合标签。您将需要使用 &lt;span&gt;&lt;/span&gt;&lt;select&gt;&lt;/select&gt;

    【讨论】:

    • 谢谢。这是一个很容易的改变。 +1(如果可以的话)提及自动关闭跨度/选择问题。
    • 我已经让a pull request 解决了这个问题($rawData 在'template' 和 'with' 绑定中被破坏),从 5 月开始开放 - 如果你能看一看,那就太好了!跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-29
    • 2017-11-25
    • 1970-01-01
    • 2013-08-26
    • 1970-01-01
    • 2017-07-26
    • 2012-11-02
    相关资源
    最近更新 更多