I am developing a custom bindingHandlers to display/edit dates in input boxes. Whenever the user is typing an invalid date, I would like to clear the input box.
Note: input boxes where dates are typed are observables (queried from breeze).
Here is my actual implementation:
ko.bindingHandlers.dateRW = {
//dateRW --> the 'read-write' version used both for displaying & updating dates
init: function (element, valueAccessor, allBindingsAccessor) {
var observable = valueAccessor();
//handle the field changing
ko.utils.registerEventHandler(element, "change", function () {
var value = $(element).val();
var dateFormatted = moment.utc(value, "DD/MM/YYYY");
if (dateFormatted!=null && dateFormatted.isValid())
observable(dateFormatted.toDate())
else {
observable(null);
}
});
},
update: function (element, valueAccessor, allBindingsAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
var date = (typeof value !== 'undefined') ? moment.utc(value) : null;
var dateFormatted = (date != null) ? date.format('DD/MM/YYYY') : '';
$(element).val(dateFormatted);
}
};
Examples working well:
- user is typing 25/12/2013 >> date is valid
- next, user is typing 1234 >> date is invalid >> the input box is cleared
- next, user is typing 01/04/2013 >> date is valid
Examples not working:
- user is typing 1234 >> date is invalid >> the input box is cleared
- next, user is typing 5678 >> date is (again!) invalid >> the input box is no more cleared!!
The reason why the input box is no more cleared is because in the previous step the observable was already set to null and we know that if an observable did not changed his value, there is no update fired.
The workaround I found is like below: forcing double successive update (undefined + null).
ko.bindingHandlers.dateRW = {
//dateRW --> the 'read-write' version used both for displaying & updating dates
init: function (element, valueAccessor, allBindingsAccessor) {
var observable = valueAccessor();
//handle the field changing
ko.utils.registerEventHandler(element, "change", function () {
var value = $(element).val();
var dateFormatted = moment.utc(value, "DD/MM/YYYY");
if (dateFormatted!=null && dateFormatted.isValid())
observable(dateFormatted.toDate())
else {
observable(undefined);
observable(null);
}
});
},
update: function (element, valueAccessor, allBindingsAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
var date = (typeof value !== 'undefined') ? moment.utc(value) : null;
var dateFormatted = (date != null) ? date.format('DD/MM/YYYY') : '';
$(element).val(dateFormatted);
}
};
I don't like proceed like that. Maybe there is a better way?
Thanks.