Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Knockout date selector - use three `<select>` elements and compute a date, also restrict date within certain range
<!doctype html>
<html>
<head>
<title>Knockout Date Selector</title>
</head>
<body style="background-color:#eee;font-family:sans-serif;">
<article style="width:600px;background-color:#fff;margin:1em auto;border:1px solid #000;padding:1em;">
<h1>Knockout Date Selector</h1>
<p>
Date of birth:
<select data-bind="value: dateOfBirthDay, options: dateOfBirthDayOptions, optionsCaption: ' '"></select> /
<select data-bind="value: dateOfBirthMonth, options: dateOfBirthMonthOptions, optionsText: 'name', optionsValue: 'value', optionsCaption: ' '"></select> /
<select data-bind="value: dateOfBirthYear, options: dateOfBirthYearOptions, optionsCaption: ' '"></select>
</p>
<p>Date of birth (Y-M-D): <strong data-bind="text: dateOfBirthText"></strong><strong style="color:red" data-bind="visible: dateOfBirthUnset">You have not set your date of birth</strong></p>
<p>Earliest valid: <strong data-bind="text: earliestValidDateOfBirthText"></strong></p>
<p>Latest valid: <strong data-bind="text: latestValidDateOfBirthText"></strong></p>
</article>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script>
<script type="text/javascript">
(function (ko) {
var AppViewModel = function() {
var year,
now = new Date(),
earliestValidDateOfBirth = new Date(now.getFullYear() - 84 - (now.getMonth() < 6 ? 1 : 0), ((now.getMonth() + 6) % 12), now.getDate()),
latestValidDateOfBirth = new Date(now.getFullYear() - 18, now.getMonth(), now.getDate()),
allDays = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 ],
allMonths = [
{ name: 'Jan', value: '0' },
{ name: 'Feb', value: '1' },
{ name: 'Mar', value: '2' },
{ name: 'Apr', value: '3' },
{ name: 'May', value: '4' },
{ name: 'Jun', value: '5' },
{ name: 'Jul', value: '6' },
{ name: 'Aug', value: '7' },
{ name: 'Sep', value: '8' },
{ name: 'Oct', value: '9' },
{ name: 'Nov', value: '10' },
{ name: 'Dec', value: '11' }
],
pad = function (value, length) {
value = value.toString();
while (value.length < length) {
value = '0' + value;
}
return value;
};
// Watch the input fields
this.dateOfBirthDay = ko.observable();
this.dateOfBirthMonth = ko.observable();
this.dateOfBirthYear = ko.observable();
// Dynamically compute the options available in the input fields
this.dateOfBirthDayOptions = ko.computed(function () {
if (this.dateOfBirthYear() <= earliestValidDateOfBirth.getFullYear() && this.dateOfBirthMonth() <= earliestValidDateOfBirth.getMonth()) {
return allDays.slice(earliestValidDateOfBirth.getDate() - 1);
} else if (this.dateOfBirthYear() >= latestValidDateOfBirth.getFullYear() && this.dateOfBirthMonth() >= latestValidDateOfBirth.getMonth()) {
return allDays.slice(0, latestValidDateOfBirth.getDate());
} else {
return allDays;
}
}, this);
this.dateOfBirthMonthOptions = ko.computed(function () {
if (this.dateOfBirthYear() <= earliestValidDateOfBirth.getFullYear()) {
return allMonths.slice(earliestValidDateOfBirth.getMonth());
} else if (this.dateOfBirthYear() >= latestValidDateOfBirth.getFullYear()) {
return allMonths.slice(0, latestValidDateOfBirth.getMonth() + 1);
} else {
return allMonths;
}
}, this);
this.dateOfBirthYearOptions = ko.computed(function () {
var year, years = [];
for (year=earliestValidDateOfBirth.getFullYear(); year<=latestValidDateOfBirth.getFullYear(); year++) {
years.push(year);
}
return years;
}, this);
// Display the earliest and latest date
this.earliestValidDateOfBirthText = ko.computed(function () {
return earliestValidDateOfBirth.getFullYear() + '-' + pad(earliestValidDateOfBirth.getMonth() + 1, 2) + '-' + pad(earliestValidDateOfBirth.getDate(), 2);
}, this);
this.latestValidDateOfBirthText = ko.computed(function () {
return latestValidDateOfBirth.getFullYear() + '-' + pad(latestValidDateOfBirth.getMonth() + 1, 2) + '-' + pad(latestValidDateOfBirth.getDate(), 2);
}, this);
// Display the selected date or error message
this.dateOfBirthUnset = ko.computed(function() {
return this.dateOfBirthDay() === undefined || this.dateOfBirthMonth() === undefined || this.dateOfBirthYear() === undefined;
}, this);
this.dateOfBirthText = ko.computed(function() {
// Ensure that all the input values are up to date
this.dateOfBirthDay.valueHasMutated();
this.dateOfBirthMonth.valueHasMutated();
this.dateOfBirthYear.valueHasMutated();
// Determine the text value
return this.dateOfBirthUnset() ? '' : this.dateOfBirthYear() + '-' + pad(parseInt(this.dateOfBirthMonth(), 10) + 1, 2) + '-' + pad(this.dateOfBirthDay(), 2);
}, this);
}
ko.applyBindings(new AppViewModel());
}(ko));
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment