4

I have a date declared as an observable in my view model like this:

self.date = ko.observable(date);

In my markup, I am declaring the control like this:

<div class="input-group">
    <input class="form-control datepicker" 
        data-bind="
            datepicker: date, 
            attr: { 
                id: 'Payments_' + $index() + '_Date', 
                name: 'Payments[' + $index() + '].Date'
            }
        "
        data-dateformat="dd/mm/yy" 
        data-val="true" 
        data-val-date="The field Date must be a date." 
        data-val-required="The Date field is required."
    />
    <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>

This is used in a Knockout JS Template and I am trying to make it place nice with the out of the box ASP.Net MVC model binding for a collection of a custom object.

I am using the following Knockout JS custom binding:

ko.bindingHandlers.datepicker = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        //initialize datepicker with some optional options
        var options = allBindingsAccessor().datepickerOptions || { dateFormat: 'dd/mm/yy' };
        $(element).datepicker(options);

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

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

    },
    //update the control when the view model changes
    update: function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor()),
            current = $(element).datepicker("getDate");

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

My problem is that when a value is selected in the Datepicker, I get the following error in Chrome:

Uncaught Missing instance data for this datepicker 
t.extend._getInst 
t.extend._selectDay
t.extend._attachHandlers.e.dpDiv.find.map.e.selectDay 
x.event.dispatch jquery.js:4692x.event.add.y.handle

If I remove the attribute binding for setting the Id and Name of the control then the error does not occur. I need to be able to set this though so that the MVC Model binding can interpret it correctly. Any suggestions or ideas would be very welcome.

Thanks

3
  • What version of knockout, 2.x or 3.x ? I'm also assuming that this HTML snippet is in a foreach binding (due to use of $index) Commented Sep 15, 2014 at 0:04
  • I have found a working example of date picker at codinglookseasy.blogspot.in/2014/07/knockoutjs.html under heading Integrate third party widgets with knockout Commented Sep 15, 2014 at 2:55
  • @RobertSlaney yes you are correct. I left out the foreach for brevity. I'm using knockout 3.1.0. G_S thanks but that example doesn't use an ID for the data bound control and that is my problem Commented Sep 15, 2014 at 8:08

1 Answer 1

9

I suspect the problem is that when the datepicker binding is applied, the id hasn't been set yet. And from what I could find online, the id is key to how the datepicker works, the datepicker is associated with the id. If it ever changes, it usually leads to problems.

Since you are using knockout 3.1, you can add the after property to your binding handler and include the attr binding to the list. This will ensure that the listed bindings are applied first before this one. And with the attr binding applied, the element should have an id by then.

ko.bindingHandlers.datepicker = {
    after: ['attr'], // add this
    init: ...,
    update: ...
};

Just beware that since your ids are being updated as you add/remove your payments. If a change alters the id of an existing control, it will detach the associated datepicker and you will see the problems again.

fiddle

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.