Knockout binding to JavaScript-dates and moment-formatting

Share on:

Data-binding an input-field or text-field to a JavaScript date is not implemented by default in Knockout. Here is a solution using MomentJS for formatting the date.

    /*
     * use like this: data-bind="date: dateVariable, format: 'YYYY-MM-DD'"
     */
    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 val = valueAccessor();

            var formatted = 'Invalid date';
            var date = moment(ko.utils.unwrapObservable(val));

            var format = allBindingsAccessor().format || 'YYYY-MM-DD';

            if (date && date.isValid()) {
                formatted = date.format(format);
            }

            if ($(element).is('input') === true) {
                $(element).val(formatted);
            } else {
                $(element).text(formatted);
            }
        }
    };