(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 o
From HTML 5 - Input type date formatting on iOS
There are two formats at play:
- displayed format
- internal format exposed to JavaScript and sent to the server
You cannot change the display format. It's up to the browser to decide how the date is presented to the user (in practice it's determined by system's locale).
You cannot change the internal format either. It's always ISO8601, regardless of browser/locale.
You'll have to pre-populate it with that specific format, and you can add a computed observable to parse it into a Date
object, so you can read it at other places in your application.
If you also want to write to it from JS, you could set up a writeable computed observable and parse the input to see if it's a string from the input field, or a Date
object from your JS.
Based off of Ryan's answer above, this works a little nicer with newer ko/chrome widgets. It also strips the time part of the date.
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();
var target_date = element.valueAsDate;
var truncated = new Date(target_date.getFullYear(), target_date.getMonth(), target_date.getDate());
value(truncated);
});
},
// Update the control whenever the view model changes
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor();
var unwrapped = ko.utils.unwrapObservable(value());
if(unwrapped === undefined || unwrapped === null) {
element.value = '';
} else {
element.valueAsDate = unwrapped;
}
}
};
Here's a solution that is working for me with the latest knockoutjs, based off of the link below and modified to have a custom init function to handle updating ko.computed properties as your date value changes.
Note that utils.formatDate is just a utility function to format the date in whatever string you want, so just replace that with your own date formatting code, whether you use momentjs or something else.
ko.bindingHandlers.date = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
ko.utils.registerEventHandler(element, 'change', function () {
var value = valueAccessor();
if (element.value !== null && element.value !== undefined && element.value.length > 0) {
value(element.value);
}
else {
value('');
}
});
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);
var output = '';
if (valueUnwrapped !== null && valueUnwrapped !== undefined && valueUnwrapped.length > 0) {
output = utils.formatDate(valueUnwrapped);
}
if ($(element).is('input') === true) {
$(element).val(output);
} else {
$(element).text(output);
}
}
};
<div>
<label>Date of Birth:</label>
<input type="text" data-bind="date: dateOfBirth, format: 'DD MMM YYYY'" />
</div>
BINDING AND FORMATTING DATES USING KNOCKOUT AND MOMENT JS
You can use the computed vartiable for the date object in your model:
In html:
<input data-bind="value : rawDate" type="date">
In code:
var currentDate = (new Date()).toISOString().split('T')[0];
// this is used instead of MyDate in the data binding
rawDate : ko.observable(currentDate),
...
// and then set up the dependent variable
viewModel.MyDate = ko.computed(function () {
var val = this.rawDate();
if (typeof val === 'string') val = new Date(val);
return val;
}, viewModel)
Please see the demo: http://jsfiddle.net/gcAXB/1/
These days is so much easier with Moment.js
this.sessionDate = ko.observable(moment().format('YYYY-MM-DD'));
this.getFormattedDate = () => { return moment(this.sessionDate()'YYYY-MM-DD').format('MM/DD/YYYY') }; // Note this is ES2015 syntax
In your html you can bind it with
<input class="form-control" name="date" type="date" id="date" data-bind="value: sessionDate">
And display it formatted as
<p data-bind="text : getFormattedDate()">Loading Date</p>
No need to create custom bindings, and you can use a shim for older browsers.
The same as this custom binding, but using momentJS:
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(moment(element.value).format());
});
},
// Update the control whenever the view model changes
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor();
element.value = moment(value()).format("YYYY-MM-DD");
}
};