ko.bindingHandlers.datepicker不适用于淘汰版3.0

时间:2014-04-10 15:02:12

标签: jquery knockout.js datepicker knockout-2.0 knockout-3.0

目前我正在使用knockout 2.1.0,其中以下的datepicker绑定完美地处理不可观察的值。当我更新了淘汰赛3.0时它无法正常工作

ko.bindingHandlers.datepicker = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        // Get the options from the binding.
        var options = allBindingsAccessor().datepickerOptions || {};

        $(element)
      .datepicker(options)
      .bind("change", function() {
          ko.bindingHandlers.datepicker.updateValue(element, valueAccessor, allBindingsAccessor);
      });

        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $(element).datepicker("destroy");
        });
    },
    update: function(element, valueAccessor, allBindingsAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());

        // If the date is coming from a Microsoft webservice.
        if (typeof value === "string" && value.indexOf('/Date(') === 0) {
            value = new Date(parseInt(value.replace(/\/Date\((.*?)\)\//gi, "$1")));
        }
        var currentDate = $(element).datepicker("getDate");

        // Check if the date has changed.
        if (value && value - currentDate !== 0) {
            $(element).datepicker("setDate", value);
        }
    },
    updateValue: function(element, valueAccessor, allBindingsAccessor) {
        var observable = valueAccessor(),
        dateValue = $(element).datepicker("getDate");

        // Two-way-binding means a writeable observable.
        if (ko.isWriteableObservable(observable)) {
            observable(dateValue);
            return;
        }
        if (allBindingsAccessor()._ko_property_writers) {
            allBindingsAccessor()._ko_property_writers.datepicker(dateValue);
        }
    }
};

当我调试代码时,我知道allBindingsAccessor()._ko_property_writers未定义。因此,我无法更新不可观察的值。

JsFIddle

有人可以建议我在3.0版本中使用上述代码的解决方案

通过使用下面的示例,我修改了我的自定义绑定,它工作得很好。请找到更新的小提琴

Updated Fiddle

1 个答案:

答案 0 :(得分:1)

问题是_ko_property_writers是一个私有实现细节(这就是为什么名称是_的前缀)。如果您阅读line 188-195 in the source code for expression rewriting in knockout,则会发现其中包含以下内容:

  

使绑定明确地将自己声明为"双向"从长远来看并不理想(如果所有绑定都可以使用官方的属性编写器API而不需要声明它们可能会更好)。但是,由于这不是,而且从未如此,公共API(_ko_property_writers从未记录过),它在短期内可以作为内部实现细节。

     

对于那些在自定义绑定中依赖_ko_property_writers的开发人员,我们将_twoWayBindings作为未记录的功能公开,这使得升级到KO 3.0相对容易。但是,这仍然不是官方的公共API,如果我们创建一个真正的公共属性编写器API,我们保留随时删除它的权利。

因此,似乎仍然没有公共API不会更改为未来版本,但您应该能够使用_twoWayBindings,直到决定并提供此类API。

更新2014-04-15 - 添加设置双向绑定标志的示例

_twoWayBindings设置(可能会在任何未来版本的淘汰赛中消失,因为它不是真正的公共API,不幸的是)是您在创建bindingHandler时可以设置的标记告诉knockout为您的_ko_property_writers创建bindingHandler条目。设置此标志的方式与创建新bindingHandler的方式类似:

ko.expressionRewriting._twoWayBindings['simpleTwoWayBinding'] = true;

绑定的完整示例,它将对不可观察的属性进行双向绑定:

ko.expressionRewriting._twoWayBindings['simpleTwoWayBinding'] = true;
ko.bindingHandlers['simpleTwoWayBinding'] = {
    init: function(element, valueAccessor, allBindings, viewModel){
        element.value = valueAccessor();
        var valueSetter = allBindings.get('_ko_property_writers').simpleTwoWayBinding;
        element.addEventListener('change', function(){
            valueSetter(element.value);
        });
    }
};

我有一个可以在http://jsfiddle.net/p8ugz/

找到的工作样本

但是,请注意上述代码不适用于可观察属性。要支持两者,您需要检查它是否绑定到一个可观察对象,并且在这种情况下只使用普通的可观察对象,如果它不是可观察的,则使用_ko_property_writers