disable jquery datepicker via knckoutjs radio button - javascript

The radio option in my application return three values allday, morning and halfday. How can I tie my jquery datepicker as such that it is enabled only when allday is selected.
var viewModel = function () {
this.holidayType = ko.observable();
this.allday = ko.computed(
{
read: function () {
return this.holidayType() == "allday";
},
write: function (value) {
if (value)
this.holidayType("allday");
}
}, this);
this.morning = ko.computed(
{
read: function () {
return this.holidayType() == "morning";
},
write: function (value) {
if (value)
this.holidayType("morning");
}
}, this);
this.afternoon = ko.computed(
{
read: function () {
return this.holidayType() == "afternoon";
},
write: function (value) {
if (value)
this.holidayType("afternoon");
}
}, this);
};
ko.applyBindings(new viewModel());
$(function () {
$("#e1").daterangepicker({
datepickerOptions: {
minDate: 0
}
});
});

First, I added an observable named dateRangeButton to your viewmodel. This observable will hold a jQuery selector to the dynamically generated <button> that is created by the date range picker plug-in:
this.dateRangeButton = ko.observable();
Then I added a function to the viewmodel called enableDisableDateRange. When called, this function will add or remove the disabled attribute to the date range picker button based on whether or not the holidayType equals "allday":
this.enableDisableDateRange = function(context) {
context.dateRangeButton().prop('disabled', context.holidayType() != 'allday');
}
How do we get the selector for the date range picker button? I created a custom binding which will apply the date range picker to the element and populate the dateRangeButton observable in the viewmodel:
ko.bindingHandlers.datePicker = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// apply the date range picker
$(element).daterangepicker({
datepickerOptions: {
minDate: 0
}
});
// tell the viewmodel where the date range picker button is
bindingContext.$data.dateRangeButton($(element).next('button'));
// enable or disable the button
bindingContext.$data.enableDisableDateRange(bindingContext.$data);
}
};
I added this binding to the <input> element that will contain the date range picker:
<input id="e1" name="e1" data-bind="datePicker: ''">
Finally, I added a subscribe to the holidayType observable which will call the enableDisableDateRange function any time holidayType changes:
this.holidayType.subscribe(function() {
this.enableDisableDateRange(this);
}, this);
Here is a fiddle: http://jsfiddle.net/6cfb1dLg/
NOTE: This all relies on how the date range picker arranges it's UI. Currently, it creates a <button> element directly after the <input> element it is applied to. If this changes, then the datePicker custom binding I wrote would have to be modified as well. The custom binding also assumes the presence of an observable named dateRangeButton and a function named enableDisableDateRange exist within the viewmodel.

Related

KendoUI ComboBox Change Event Runs Multiple Times

I have an MVC Control for a KendoUI ComboBox that does NOT setup the Change Event ahead of time. Upon rendering, a page controller sets-up & shims-in its' own Change Event.
Oddly, this event gets called TWICE:
When I change the Selected Item
When I click away from the control
Q: What am I doing wrong?
Q: Is this HOW we should over-write the change event on an existing Kendo ComboBox?
MVC CONTROL:
As you can see, I am NOT defining any client-side events here...
#(Html.Kendo().ComboBox()
.Name("ddlTechnician")
.Filter("contains")
.Placeholder("Select Technician...")
.DataTextField("Text")
.DataValueField("Value")
.BindTo(new List<SelectListItem>() {
new SelectListItem() { Text = "Frank", Value = "1" },
new SelectListItem() { Text = "Suzie", Value = "2" },
new SelectListItem() { Text = "Ralph", Value = "3" }
})
.Suggest(true)
.HtmlAttributes(new { style = "width:300px;" }))
PAGE CONTROLLER:
And, I am only defining the event ONCE here. I have also confirmed the event isn't already firing BEFORE setting it in the Page Controller
$(document).ready(function () {
var PageController = (function ($) {
function PageController(options) {
var that = this,
empty = {},
dictionary = {
elements: {
form: null
},
instances: {
ddlTechnician: null
},
selectors: {
form: 'form',
ddlTechnician: '#ddlTechnician'
}
};
var initialize = function (options) {
that.settings = $.extend(empty, $.isPlainObject(options) ? options : empty);
dictionary.elements.form = $(dictionary.selectors.form);
// Objects
dictionary.instances.ddlTechnician = $(dictionary.selectors.ddlTechnician, dictionary.elements.form).data('kendoComboBox');
// Events
dictionary.instances.ddlTechnician.setOptions({ change: that.on.change.kendoComboBox });
};
this.settings = null;
this.on = {
change: {
kendoComboBox: function (e) {
// This is getting called MULTIPLE TIMES
console.log('kendoComboBox RAN');
}
}
}
};
initialize(options);
}
return PageController;
})(jQuery);
var pageController = new PageController({});
});
I was able to reproduce your problem on a Kendo JQuery Combobox when I set the event handler through setOptions, which is not the recommended way after the widget has been rendered. Instead you should use the "bind" method as shown in the documentation's example for change events.
Try changing the line of code where you set your event handler to this:
dictionary.instances.ddlTechnician.bind("change", that.on.change.kendoComboBox);
Here's a dojo that shows the difference: http://dojo.telerik.com/iyEQe
Hope this helps.

How to set default time and minute

In this fiddle inside the view appointments tab,there is add timing button.When I click on the button then a new row gets added.Now when I click on the calender icon then a pop comes up which shows the current hour and minutes.But I want it to show 00:00. Can any body please tell me how to do?
I have tried to modify the setDate method inside the bootstrap date time picker source code
setLocalDate: function (localDate) {
if (!localDate)
this.setValue(null);
else
this.setValue(Date.UTC(localDate.getFullYear(), localDate.getMonth(), localDate.getDate(), localDate.getHours(), localDate.getMinutes(), localDate.getSeconds(), localDate.getMilliseconds()))
},
to
setLocalDate: function (localDate) {
if (!localDate)
this.setValue(null);
else
this.setValue(00, 00, 00, 00,00, 00, 00))
},
but it did not work.Please anybody tell me what else do I have to change
As #RobG already said, you can simply set the value in the initialization routine
ko.bindingHandlers.datepicker1 = {
init: function (element, valueAccessor, allBindingsAccessor) {
$(function () {
$(element).parent().datetimepicker({
pickDate: false,
pickSeconds: false,
minuteStep: 10
});
$(element).parent().datetimepicker('setValue', '00:00');
});
// ...
See updated JSFiddle
Update:
If you want 00:00 as default value only, you must pick the value from the valueAccessor first and set 00:00, if the value is undefined
init: function (element, valueAccessor, allBindingsAccessor) {
$(function () {
$(element).parent().datetimepicker({
pickDate: false,
pickSeconds: false,
minuteStep: 10
});
var accessor = valueAccessor();
var val = ko.unwrap(accessor) || '00:00';
$(element).parent().datetimepicker('setValue', val);
});
// ...
See JSFiddle
Update:
Unfortunately, I cannot find any documentation about version 2.2.0.
Testing, if the accessor is a function, seems to work
var val = valueAccessor();
if (typeof(val) == 'function')
val = val();
$(element).parent().datetimepicker('setValue', val || '00:00');
Updated JSFiddle

Creating a clean Knockout binding without business logic (Popover - Radio Buttons)

I'm looking for a clean way to implement the following. Let's assume I have 5 buttons:
(Dog) - (Cat) - (Fish) - (Bird) - (Other)
In my ViewModel these buttons are represented as being a classification. So when I click the Dog button, the observable in my ViewModel should be set to Dog (this would be done through the click binding on each button).
Also, I want to show a specific style when one of the buttons is toggled (done by the css binding on the button):
(Dog) - (Cat) - (Fish) - (Bird) - (Other)
So for now this looks like it should turn my buttons into a radio button group. Now besides that, when I click the "Other" button I also want to show a little popover (bootstrap) in which the user can specifiy a custom value, like "Lion". Clicking an other button would close the popover.
Now on each button I could add a binding similar to this one:
{ css: { 'toggled': classficationMatches('Dog') },
popover: { action: 'close', id: 'mypopover' },
click: { click:setClassification.bind($data, 'Dog') }
But this feels dirty. I would prefer building a custom handler and use it like this:
{ toggleClassification: { type: 'Dog', popover: 'mypopover' } }
Now it would be up to the ViewModel to decided if the popover should be visible or not and the binding would contain all the logic of adding the css binding, the click and the popover bindings to the buttons.
I started trying some things with custom bindings but this code looks even worse:
ko.bindingHandlers["toggleClassification"] = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var classification = $(element).attr('data-type');
var selector = ko.utils.unwrapObservable(valueAccessor());
var pickerViewModel = new SimpleFilterSpecializationPickerViewModel(element, selector);
// Whenever we click the button, show the popover.
ko.utils.registerEventHandler(element, "click", function () {
// Hide the popup if it was visible.
if (pickerViewModel.isVisible()) {
pickerViewModel.hide();
}
else {
var requireInit = !pickerViewModel.loaded();
// Show the popover.
pickerViewModel.show();
// The first time we need to bind the popover to the view model.
if (requireInit) {
ko.applyBindings(viewModel, pickerViewModel.getPopoverElement());
// If the classification changes, we might not want to show the popover.
viewModel.isClassification(classification).subscribe(function () {
if (!viewModel.isClassification(classification)()) {
pickerViewModel.hide();
}
});
}
}
$('button[data-popoverclose]').click(function () {
$(element).popover('hide');
});
});
}
};
ko.bindingHandlers["toggleClassification"] = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
// Store the current value on click.
$(element).click(function () {
var observable = valueAccessor();
viewModel.setClassification(observable);
});
// Update the css of the button.
ko.applyBindingsToNode(element, { css: { 'active': viewModel.isClassification(valueAccessor()) } }, viewModel);
}
};
Anyone have some tips on how I could clean up my bindings so most of the 'logic' can be done in the ViewModel?
You can add this "dirty" binding programmatically with
ko.applyBindingsToNode(Element element, Object bindings, Object viewModel)
e.g.
HTML
data-bind="toggleClassification: { type: 'Dog', popover: 'mypopover' }"
JS
ko.bindingHandlers["toggleClassification"] =
{
init: function (element, valueAccessor, allBindings, viewModel, bindingContext)
{
var type = valueAccessor().type; // 'Dog'
var popover = valueAccessor().popover; // 'mypopover'
var binding = {
css: { 'toggled': classficationMatches(type) },
popover: { action: 'close', id: popover },
click: { click:setClassification.bind(bindingContext.$data, type) }
};
ko.applyBindingsToNode(element, binding , viewModel);
}
};

Knockout change while jQuery Datepicker is open breaks Datepicker

I've set up a jsFiddle to demonstrate my problem.
What I'm doing:
I'm using Knockout with a jQuery Datepicker as shown in this question.
My model contains an observableArray which contains objects with date properties. Knockout renders an <input type="text"> for every object, and binds the value to the date using RP Niemeyer's datepicker binding.
What's going wrong:
If the user has a datepicker open when knockout's model changes (e.g., adding a new item), the datepicker stops working correctly. From what I can tell, the last <input type="text"> created while the datepicker is open becomes the new datepicker target. I need to fix the binding so that this does not happen.
Sample HTML:
<ul data-bind="foreach: dateBoxes">
<li>
<span data-bind="text: index"></span>
<input type="text" data-bind="datepicker: date"/>
</li>
</ul>
Sample Javascript:
ko.bindingHandlers.datepicker = {
init: function(element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {};
$(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: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
//handle date data coming via json from Microsoft
if (String(value).indexOf('/Date(') == 0) {
value = new Date(parseInt(value.replace(/\/Date\((.*?)\)\//gi, "$1")));
}
var current = $(element).datepicker("getDate");
if (value - current !== 0) {
$(element).datepicker("setDate", value);
}
}
};
var model;
var id = 0;
function DateBox(d) {
var self = this;
self.date = ko.observable(d);
self.index = ko.observable(id++);
}
function Model() {
var self = this;
self.dateBoxes = ko.observableArray([]);
self.changeCount = function() {
if (self.dateBoxes().length < 2) {
self.dateBoxes.push(new DateBox(new Date()));
} else if (self.dateBoxes().length > 1) {
self.dateBoxes.splice(0,1);
}
}
self.tick = function() {
self.changeCount();
setTimeout(function() {
self.tick();
}, 5000);
}
self.tick();
}
model = new Model();
ko.applyBindings(model);
Note: This answer isn't complete. However, as it's too large for a comment and probably helpful (towards a solution) anyhow I've taken the liberty and posted it as an answer. Anyone that can complete this answer is invited to do so through an edit or by spinning off into another better answer.
The thing that seems to be spoiling the party (taken from the documentation, emphasis mine):
This will be called once when the binding is first applied to an element, and again whenever the associated observable changes value.
If I hackisly prevent the update from doing its datepicker calls in the first update the datepicker won't break anymore (other issues do arise though). For the init I've added this line at the end:
element.isFirstRun = true;
Then the update method will do the following just before the datepicker calls:
if (element.isFirstRun) {
$(element).val(value);
element.IsFirstRun = false;
return;
}
See this updated fiddle for the results, which are:
the mentioned scenario now updates the correct textbox (a good thing);
the initial value is now a more verbose DateTime string and stays that way after updates (kinda not nice);
Hopefully this will help towards a more complete solution.

how to use datepicker with knockout [duplicate]

I'm trying to use KnockoutJS with jQuery UI. I have an input element with a datepicker attached. I'm currently running knockout.debug.1.2.1.js and it seems that the change event is never being caught by Knockout. The element looks like this:
<input type="text" class="date" data-bind="value: RedemptionExpiration"/>
I've even tried changing the valueUpdate event type but to no avail. It seems like Chrome causes a focus event just before it changes the value, but IE doesn't.
Is there some Knockout method that "rebinds all the bindings"? I technically only need the value changed before I send it back to the server. So I could live with that kind of workaround.
I think the problem's the datepicker's fault, but I can't figure out how to fix this.
Any ideas?
I think that for the jQuery UI datepicker it is preferable to use a custom binding that will read/write with Date objects using the APIs provided by the datepicker.
The binding might look like (from my answer here):
ko.bindingHandlers.datepicker = {
init: function(element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {},
$el = $(element);
$el.datepicker(options);
//handle the field changing by registering datepicker's changeDate event
ko.utils.registerEventHandler(element, "changeDate", function () {
var observable = valueAccessor();
observable($el.datepicker("getDate"));
});
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$el.datepicker("destroy");
});
},
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
$el = $(element);
//handle date data coming via json from Microsoft
if (String(value).indexOf('/Date(') == 0) {
value = new Date(parseInt(value.replace(/\/Date\((.*?)\)\//gi, "$1")));
}
var current = $el.datepicker("getDate");
if (value - current !== 0) {
$el.datepicker("setDate", value);
}
}
};
You would use it like:
<input data-bind="datepicker: myDate, datepickerOptions: { minDate: new Date() }" />
Sample in jsFiddle here: http://jsfiddle.net/rniemeyer/NAgNV/
Here is a version of RP Niemeyer's answer that will work with the knockout validation scripts found here: http://github.com/ericmbarnard/Knockout-Validation
ko.bindingHandlers.datepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {};
$(element).datepicker(options);
//handle the field changing
ko.utils.registerEventHandler(element, "change", function () {
var observable = valueAccessor();
observable($(element).val());
if (observable.isValid()) {
observable($(element).datepicker("getDate"));
$(element).blur();
}
});
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).datepicker("destroy");
});
ko.bindingHandlers.validationCore.init(element, valueAccessor, allBindingsAccessor);
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
//handle date data coming via json from Microsoft
if (String(value).indexOf('/Date(') == 0) {
value = new Date(parseInt(value.replace(/\/Date\((.*?)\)\//gi, "$1")));
}
current = $(element).datepicker("getDate");
if (value - current !== 0) {
$(element).datepicker("setDate", value);
}
}
};
Changes are to the change event handler to pass the entered value and not the date to the validation scripts first, then only setting the date to the observable if it is valid. I also added the validationCore.init that is needed for custom bindings discussed here:
http://github.com/ericmbarnard/Knockout-Validation/issues/69
I also added rpenrose's suggestion for a blur on change to eliminate some pesky datepicker scenarios getting in the way of things.
I've used a different approach. Since knockout.js doesn't seem to fire the event on change, I've forced the datepicker to call change() for its input once closed.
$(".date").datepicker({
onClose: function() {
$(this).change(); // Forces re-validation
}
});
Although all of these answers saved me a lot of work, none of them fully worked for me. After selecting a date, the binded value would not update. I could only get it to update when changing the date value using the keyboard then clicking out of the input box. I fixed this by augmenting RP Niemeyer's code with syb's code to get:
ko.bindingHandlers.datepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {};
var funcOnSelectdate = function () {
var observable = valueAccessor();
observable($(element).datepicker("getDate"));
}
options.onSelect = funcOnSelectdate;
$(element).datepicker(options);
//handle the field changing
ko.utils.registerEventHandler(element, "change", funcOnSelectdate);
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).datepicker("destroy");
});
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
if (typeof(value) === "string") { // JSON string from server
value = value.split("T")[0]; // Removes time
}
var current = $(element).datepicker("getDate");
if (value - current !== 0) {
var parsedDate = $.datepicker.parseDate('yy-mm-dd', value);
$(element).datepicker("setDate", parsedDate);
}
}
};
I suspect putting the observable($(element).datepicker("getDate")); statement in its own function and registering that with options.onSelect did the trick?
Thanks for this article I found it very useful.
If you want the DatePicker to behave exactly like the JQuery UI default behaviour I recommend adding a blur on the element in the change event handler:
i.e.
//handle the field changing
ko.utils.registerEventHandler(element, "change", function () {
var observable = valueAccessor();
observable($(element).datepicker("getDate"));
$(element).blur();
});
I solved this problem by changing the order of my included script files:
<script src="#Url.Content("~/Scripts/jquery-ui-1.10.2.custom.js")"></script>
<script src="#Url.Content("~/Scripts/knockout-2.2.1.js")"></script>
Same as RP Niemeyer, but better support of WCF DateTime, Timezones and Using the DatePicker onSelect JQuery property.
ko.bindingHandlers.datepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {};
var funcOnSelectdate = function () {
var observable = valueAccessor();
var d = $(element).datepicker("getDate");
var timeInTicks = d.getTime() + (-1 * (d.getTimezoneOffset() * 60 * 1000));
observable("/Date(" + timeInTicks + ")/");
}
options.onSelect = funcOnSelectdate;
$(element).datepicker(options);
//handle the field changing
ko.utils.registerEventHandler(element, "change", funcOnSelectdate);
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).datepicker("destroy");
});
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
//handle date data coming via json from Microsoft
if (String(value).indexOf('/Date(') == 0) {
value = new Date(parseInt(value.replace(/\/Date\((.*?)\)\//gi, "$1")));
}
current = $(element).datepicker("getDate");
if (value - current !== 0) {
$(element).datepicker("setDate", value);
}
}
};
Enjoy :)
http://jsfiddle.net/yechezkelbr/nUdYH/
I think it can be done much easier: <input data-bind="value: myDate, datepicker: myDate, datepickerOptions: {}" />
So you do not need manual change handling in init function.
But in this case, your 'myDate' variable will get only visible value, not Date object.
Alternatively, you can specify this in binding:
Update:
function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
current = $(element).datepicker("getDate");
if (typeof value === "string") {
var dateValue = new Date(value);
if (dateValue - current !== 0)
$(element).datepicker("setDate", dateValue);
}
}
Based on Ryan's solution, myDate returns the standard date string, which is not the ideal one in my case. I used date.js to parse the value so it will always return the date format you want. Take a look at this example fiddle Example.
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
current = $(element).datepicker("getDate");
var d = Date.parse(value);
if (value - current !== 0) {
$(element).datepicker("setDate", d.toString("MM/dd/yyyy"));
}
}
I needed to repeatedly update my data from the server came across this but didn't quite finish the job for my needs sharing below(my date format /Date(1224043200000)/):
//Object Model
function Document(data) {
if (String(data.RedemptionExpiration).indexOf('/Date(') == 0) {
var newDate = new Date(parseInt(data.BDate.replace(/\/Date\((.*?)\)\//gi, "$1")));
data.RedemptionExpiration = (newDate.getMonth()+1) +
"/" + newDate.getDate() +
"/" + newDate.getFullYear();
}
this.RedemptionExpiration = ko.observable(data.RedemptionExpiration);
}
//View Model
function DocumentViewModel(){
///additional code removed
self.afterRenderLogic = function (elements) {
$("#documentsContainer .datepicker").each(function () {
$(this).datepicker();
});
};
}
After the model is formatted correctly for the output I added a template with the documentation knockoutjs:
<div id="documentsContainer">
<div data-bind="template: { name: 'document-template', foreach: documents, afterRender: afterRenderLogic }, visible: documents().length > 0"></div>
</div>
//Inline template
<script type="text/html" id="document-template">
<input data-bind="value: RedemptionExpiration" class="datepicker" />
</script>
Few people asked for dynamic datepicker options. In my case I needed a dynamic date range - so the first input defines the min value of the second and the second sets the max value for the first. I solved it by extending the RP Niemeyer's handler. So to his original:
ko.bindingHandlers.datepicker = {
init: function(element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {},
$el = $(element);
$el.datepicker(options);
//handle the field changing by registering datepicker's changeDate event
ko.utils.registerEventHandler(element, "change", function() {
var observable = valueAccessor();
observable($el.datepicker("getDate"));
});
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$el.datepicker("destroy");
});
},
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
$el = $(element);
//handle date data coming via json from Microsoft
if (String(value).indexOf('/Date(') == 0) {
value = new Date(parseInt(value.replace(/\/Date\((.*?)\)\//gi, "$1")));
}
var current = $el.datepicker("getDate");
if (value - current !== 0) {
$el.datepicker("setDate", value);
}
}
};
I've added two more handlers corresponding to the options I wanted to modify:
ko.bindingHandlers.minDate = {
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
current = $(element).datepicker("option", "minDate", value);
}
};
ko.bindingHandlers.maxDate = {
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
current = $(element).datepicker("option", "maxDate", value);
}
};
And used them like that in my template:
<input data-bind="datepicker: selectedLowerValue, datepickerOptions: { minDate: minValue()}, maxDate: selectedUpperValue" />
<input data-bind="datepicker: selectedUpperValue, datepickerOptions: { maxDate: maxValue()}, minDate: selectedLowerValue" />
Using custom bindings provided in previous answers is not always possible. Calling $(element).datepicker(...) takes some considerable time, and if you have, for example, a few dozens, or even hundreds of elements to call this method with, you have to do it "lazy", i.e. on demand.
For example, the view model may be initialized, the inputs being inserted into the DOM, but the corresponding datepickers will only be initialized when a user clicks them.
So, here is my solution:
Add a custom binding that allows to attach arbitrary data to a node:
KO.bindingHandlers.boundData = {
init: function(element, __, allBindings) {
element.boundData = allBindings.get('boundData');
}
};
Use the binding to attcah the observable used for the input's value:
<input type='text' class='my-date-input'
data-bind='textInput: myObservable, boundData: myObservable' />
And finally, when initializing the datepicker, use it's onSelect option:
$('.my-date-input').datepicker({
onSelect: function(dateText) {
this.myObservable(dateText);
}
//Other options
});
This way, every time a user changes the date with the datepicker, the corresponding Knockout observable is also updated.

Categories

Resources