4

I think I can easily bind a date data with jquery ui calendar and knockout.js thanks to this answer.

Now I need to bind a date data as well as its time. Of course, I can use timepicker. But I am not sure how I can bind its data with knockout.js. I expected it'd be similar to datepicker so I made following script

    ko.bindingHandlers.datetimepicker = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            //initialize datepicker with some optional options
            var options = allBindingsAccessor().datetimepickerOptions || {};
            $(element).datetimepicker(options);

            //handle the field changing
            ko.utils.registerEventHandler(element, "change", function () {
                var observable = valueAccessor();
                observable($(element).datetimepicker("getDate"));//****
            });

            //handle disposal (if KO removes by the template binding)
            ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
                $(element).datetimepicker("destroy");
            });

        },
        update: function (element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor()),
                current = $(element).datetimepicker("getDate");

            if (value - current !== 0) {
                $(element).datetimepicker("setDate", value);
            }
        }
    };

But when I ran the script, I get an error in line of //**** in javascript

TypeError: observable is not a function

But I can't find what I did wrong here.

Community
  • 1
  • 1
Tae-Sung Shin
  • 20,215
  • 33
  • 138
  • 240

3 Answers3

2

This particular error is due to the observable = valueAccessor() line. You are assigning to observable the value of valueAccessor by adding the () to the end. In order to pass a value to observable in this way, you would need to write instead:

var observable = valueAccessor;

Otherwise, observable is not an 'observable function'.

chrisco512
  • 629
  • 3
  • 10
  • You are right. It's working now. But the reason why the same code worked for datepicker is the thing I don't understand. – Tae-Sung Shin Aug 06 '12 at 21:47
  • I just find out that your answer is wrong. valueAccessor() should give the correct knockout observalue. If I use what you suggested `valueAccessor`, the control will never work! – Tae-Sung Shin Aug 30 '12 at 22:44
  • This answer is half correct: the [documentation specifically does what OP does](http://knockoutjs.com/documentation/custom-bindings.html#modifying-observables-after-dom-events). However, it depends on how the binding was defined (see: http://stackoverflow.com/a/18015621). – Benny Bottema Apr 28 '15 at 14:16
1

I just found following code is working. As few open source code do, this addon is not very stable and will call change event with null observable sometimes. So I made the code to catch the exception and move on.

    ko.bindingHandlers.datetimepicker = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            //initialize datepicker with some optional options
            var options = allBindingsAccessor().datetimepickerOptions || {};
            $(element).datetimepicker(options);

            //handle the field changing
            ko.utils.registerEventHandler(element, "change", function () {
                var observable = valueAccessor();
                try {
                    observable($(element).datetimepicker("getDate"));//****
                }
                catch(ex) {}
            });

            //handle disposal (if KO removes by the template binding)
            ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
                $(element).datetimepicker("destroy");
            });

        },
        update: function (element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor()),
                current = $(element).datetimepicker("getDate");

            if (value - current !== 0) {
                $(element).datetimepicker("setDate", value);
            }
        }
    };
Tae-Sung Shin
  • 20,215
  • 33
  • 138
  • 240
-1

Replace this line

var observable = valueAccessor(); 

With

var xxxx= valueAccessor();

Because you cannot use the observable, because it is reserved keyword in knockout.

Also, you may get error somewhere in future if you use observable as variable name.

M.javid
  • 6,387
  • 3
  • 41
  • 56
nikhil
  • 203
  • 1
  • 10
  • 1
    This makes no sense. Reserved keywords is a javascript feature, not a knockoutjs feature, moreover this concerns a limited scoped variable, which would have no impact on existing global variables of the same name. – Benny Bottema Apr 28 '15 at 14:19