Pregunta

Currently i am using knockout 2.1.0 where following datepicker binding working perfectly for non observable value.When i have updated knockout 3.0 it is not working

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);
        }
    }
};

When i debug the code i came to know that is allBindingsAccessor()._ko_property_writers is undefined .because of which i am not able to update the nonobservable value.

JsFIddle

Can anybody suggest me the solution for above code in 3.0 version

By using below example i have modified the my custom binding and it is working great .Please find the Updated fiddle

Updated Fiddle

¿Fue útil?

Solución

The problem is that _ko_property_writers is a private implementation detail (which is why the name is prefix with _). If you read line 188-195 in the source code for expression rewriting in knockout you'll see that it states the following:

Making bindings explicitly declare themselves as "two way" isn't ideal in the long term (it would be better if all bindings could use an official 'property writer' API without needing to declare that they might). However, since this is not, and has never been, a public API (_ko_property_writers was never documented), it's acceptable as an internal implementation detail in the short term.

For those developers who rely on _ko_property_writers in their custom bindings, we expose _twoWayBindings as an undocumented feature that makes it relatively easy to upgrade to KO 3.0. However, this is still not an official public API, and we reserve the right to remove it at any time if we create a real public property writers API.

So it would seem like there is still not a public API which won't change to future versions, but you should be able to use _twoWayBindings until such an API is decided and provided.

UPDATED 2014-04-15 - Adding a sample of setting the two way binding flag

The _twoWayBindings setting (which might disappear in any future version of knockout, since it's not really a public API, unfortunately) is a flag you can set when you create your bindingHandler to tell knockout to create a _ko_property_writers entry for your bindingHandler. The way you set this flag is similar to how you create a new bindingHandler:

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

A complete example of a binding which would do two way binding to non-observable properties:

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);
        });
    }
};

I have a working sample which you can find at http://jsfiddle.net/p8ugz/

However, do be aware that the above code will not work with observable properties. To support both, you need to check if it's bound to an observable and just work with ordinary observables in that case and with the _ko_property_writers if it's not an observable.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top