3
votes

I have a custom knockoutJs binding for the date picker.

ko.bindingHandlers.valueAsDatePicker = {...}

When the bound input field status (enabled/disabled) is bound to a KO observable it doesn't enable/disable the datepicker icon.

HTML

<input id="txtRequestedTo" type="text" placeholder="dd/mm/yyyy" 
data-bind="valueAsDatePicker: reqDateTo, disable: reqDateFrom().length < 1" />

Custom Binding

ko.bindingHandlers.valueAsDatePicker = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor);
        formatAndSetDateValue(element, valueAccessor, allBindingsAccessor);

        // Init UI datepicker
        var dateFormat = allBindingsAccessor.dateFormat 

        $(element).datepicker({
            dateFormat: dateFormat,
            changeMonth: true, 
            changeYear: true, 
            yearRange: '1900:' + new Date().getFullYear(), 
            maxDate: 0, 
            showOn: "button",
            buttonImage: "Content/images/sprite-base/sprite/icon-calender.png",
            buttonImageOnly: true,
            constrainInput: false, 
            buttonText: ""          
        });
    },
    update: function(element, valueAccessor, allBindingsAccessor) {
        // Use the value binding
        ko.bindingHandlers.value.update(element, valueAccessor, allBindingsAccessor);
        formatAndSetDateValue(element, valueAccessor, allBindingsAccessor);

        valueAccessor().valueHasMutated(); 
    }
};

I want the datepicker to be disabled if the element is disabled, and Vice Versa.

2

2 Answers

2
votes

Thanks a million Robert,

Here is the solution that worked.

Using KnockOutJS V3.1

init: function (element, valueAccessor, allBindings) {
...

//Disable the datepicker if the item is disabled or enabled.
    if (allBindings.has('disable')) {
        if (allBindings.get('disable')()) {
            $(element).datepicker('disable');
        }
        else {
            $(element).datepicker('enable');
        }
        var subscription = allBindings.get('disable').subscribe(function (newValue) {
            if (newValue) {
                $(element).datepicker('disable');
            } else {
                $(element).datepicker('enable');
            }
        });

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            subscription.dispose();
        });
    }
}

You have to use

if (allBindings.has('disable')) {

otherwise

allBindings.get('disable')

will be undefined as not all datepicker bound fields in the view have the disabled attribute.

1
votes

The trick here is to get access to the disabled binding as an observable so you can attach a manual subscription. At the moment the result of the disable expression is passed into bindingHandler ( via allBindingAccessor ).

One you get a subscription you can invoke DatePicker's disable option

HTML

<input id="txtRequestedTo" type="text" placeholder="dd/mm/yyyy"
    data-bind="valueAsDatePicker: reqDateTo, disable: reqDateFrom.disabled" />

JAVASCRIPT

var reqDateFrom = ko.observable();
var reqDateTo = ko.observable();
reqDateTo.disabled = ko.computed( function() { 
     return (reqDateFrom() || '').length === 0; 
} );


ko.bindingHandlers.valueAsDatePicker {
    init: function(element, valueAccessor, allBindingsAccessor) {
        ....
        // ko 3.0 syntax.  For 2.x use allBindingAccessor['disable']
        var subscription = allBindingAccessor.get('disable').subscribe( function(newValue) {
            $(element).datepicker('option', 'disabled', newValue);
        });

        // Make sure the subscription is disposed when the element is torn down
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            subscription.dispose();
        });
    },
    update: function(element, valueAccessor, allBindingsAccessor) {
    }
}