Using Knockout.js how do bind a Date property to a HTML5 date picker?
html, javascript, knockout.js
Solution
While @amakhrov answer will work (and would be even better if used writeable computed observable like sujested by @Stijn) I decided to do this using Custom Bindings.
The main advantage of doing this is reusability - I just have to use `data-bind="datePicker : MyDate"` whereever I want to tie this in. I can also modify other properties of the input element so this could be really useful if binding to complex jQuery (and other) controls.
(Read here for more pro/cons about the 3 choices to do this sort of thing)
HTML
<input data-bind="datePicker : MyDate" type="date">
JS
ko.bindingHandlers.datePicker = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
// Register change callbacks to update the model
// if the control changes.
ko.utils.registerEventHandler(element, "change", function () {
var value = valueAccessor();
value(new Date(element.value));
});
},
// Update the control whenever the view model changes
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor();
element.value = value().toISOString();
}
};
var viewModel = {
MyDate : ko.observable(new Date())
};
ko.applyBindings(viewModel);
See http://jsfiddle.net/LLkC4/5/
Problem
(this only works in Chrome at the moment as most browsers don't yet implement date picker for input type="date") In the following example MyDate starts out as a Date object with the current date, but this isn't picked up by the date input (which expects its format to be a string in format YYYY/MM/DD). Once you've picked a date in the picker then MyDate becomes a string in format above. How can you bind this so MyDate stays a javascript Date and is interpreted by the input control correctly? See See http://jsfiddle.net/LLkC4/3/ :- ``` <input data-bind="value : MyDate" type="date"> <hr> <span data-bind="html: log" /> <script> var viewModel = { MyDate : ko.observable(new Date()), log : ko.observable(""), logDate : function () { this.log(this.log() + this.MyDate() + " : " + typeof(this.MyDate()) + "<br>"); } }; viewModel.MyDate.subscribe(function (date) { viewModel.logDate(); }); ko.applyBindings(viewModel); viewModel.logDate() </script> ```