4

Using the Editable Grid Example from Knockout, and tying in the Steve Sanderson blog, I am trying to get a DatePicker or datetimepicker to work within the editable grid. I started by using the datepicker binding set up by Ryan Niemeyer, but this doesn't work for an observable array.

So the code looks like:

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();
            console.log("changing", observable);
            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");
        console.log("updating");
        if (value - current !== 0) {
            console.log("setting", value);
            $(element).datetimepicker("setDate", value); 
            console.log("just set", $(element).datetimepicker("getDate"));            
        }
    }
};

with the binding:

<td><input class ="datetimeClass" style="width:130px" data-bind="datetimepicker: CPDateString, uniqueName: true" /></td> 

Any help or examples would be greatly appreciated. I know this has to do with each item in the observeablearray is not itself observable, but new to Javascript I can't figure out how to fix it.

I get an error: "string is not a function" on the Change event. If I add some code to try and make the field observable, like so:

 $(initialData).each(function(gift) { 
    this.CPDateString = ko.observable(this.CPDateString); 
}); 

then the datetimepicker works, and updates the browser correctly, but the data isn't posted, so it isn't updating the actual gifts array that is getting posted back by:

var initialDataLocations = @Html.Raw(JsonConvert.SerializeObject(ViewBag.Locations));

var initialData = @Html.Raw(JsonConvert.SerializeObject(Model));

var viewModel = {
    availableLocations: ko.observableArray(initialDataLocations),
    gifts: ko.observableArray(initialData),
    save: function() {      
        ko.utils.postJson(location.href, { gifts: this.gifts })
        }
    };

Thanks in advance.

rayk
  • 81
  • 1
  • 2
  • Is `this` in the save function pointing to the viewModel? You could use `arrayMap` to map the initialData like this: gifts: ko.utils.arrayMap(initialData, function(gift) { return new Gift(gift.CPDateString); }); – mhu Feb 21 '13 at 16:17

1 Answers1

3

Custom binding is powerful tool to use widget UI control. You just need to use datetimepicker custom binding to make textbox/input becomes a datetime picker and the value of input just use standard ko binding:

<td><input class ="datetimeClass" style="width:130px" data-bind="datetimepicker: {}, value:CPDateString, uniqueName: true" /></td> 

Hope this will help

update with example:

I wrote a very simple datepicker custom binding as follows:

ko.bindingHandlers.datepicker = {
    init: function (element, valueAccessor) {
        var options = valueAccessor();
        $(element).datepicker(options || {});
    }
};

And in html code just use custom binding as follows:

<input id="txtFromtDate" data-bind="datepicker:{}, value:lastUpdateFrom" type="text" />
Community
  • 1
  • 1
Anh Bui
  • 283
  • 1
  • 8
  • I've tried your solution of putting both in the data-bind, but now I'm getting an error: "Object # has no method 'getTime'". I imagine this error has to do with the fact that I'm trying to just use a String instead of a true Date object. I will keep pressing forward. – rayk Feb 21 '13 at 18:29