I have a webpage which has a repeating partial view which is being bound to a Knockout template. Within that view, I have a datepicker. That view can be added any number of times on a button click. The selection of a date in section 1, sets the minDate of the datepicker in section 2, and so on. Each section has its own Knockout view model, which has a minDate observable. Attached to this observable, I have a custom binding with an update handler - I use this to update the minDate of an element when a section is added or updated.
I have the code working up to the point where I can update the value of a datepicker in any section, and the following section will have its minDate correctly updated. Here is the code for my custom binding:
ko.bindingHandlers.minDate = {
update: function (element, valueAccessor, allBindings, viewModel) {
var value = valueAccessor();
var valueUnwrapped = ko.unwrap(value);
var oneDay = 1000 * 60 * 60 * 24;
var diff = Math.ceil((new Date(valueUnwrapped) - new Date()) / oneDay);
$(element).datepicker('option', 'minDate', diff + 1);
}
};
My problem is that if I have existing sections with dates selected and I click to add a new a new section, I can see the minDate of my newly added view model is correctly set, but that minDate is not being set on my newly added datepicker element.
If I step through my script code, the only difference I can see is that even thought at the point I break execution, my partial view has been rendered and my $(element) is indeed an object but it does not have an ID attribute. This is the only difference I can see between my working and non-working code.
Can anyone see this as a possible cause for my problem with setting the minDate on a dynamically added element?
In my code where I add dynamic sections, I originally had:
var newSection = new Components.Booking.TripViewModel();
var prevTrip = last(self.model.trips());
newSection.model.minDate(prevTrip.model.departureDate());
self.model.trips.push(newTrip);
When I realised that when I added a new view model to my section collection, that is the point at which the template renders my partial view and applies the bindings etc., which is also when the element was being assigned an ID. I simply needed to reverse the order of the last two lines, to ensure that my minDate observable is updated after the element has been bound up, and therefore when my update handler within the custom binding fires after the element has been fully rendered.
self.model.trips.push(newTrip);
newSection.model.minDate(prevTrip.model.departureDate());