0

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.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Bronzato
  • 9,438
  • 29
  • 120
  • 212

1 Answers1

0

I think what you are looking for is the valueHasMutated function that may be called on an observable to force it to update its subscribers with the latest value. In your example, you could then replace:

observable(undefined);                    
observable(null);

with:

observable.valueHasMutated();

or:

observable.notifySubscribers(null);
Jalayn
  • 8,934
  • 5
  • 34
  • 51
  • Unfortunately it doesn't work. I got the error `dependentObservable has no method valueHasMutated`. – Bronzato Apr 29 '13 at 12:43
  • it's a computed observable ? – Jalayn Apr 29 '13 at 12:45
  • This is not a computed observable.This is an observable provided by breeze (querried a table where each fields are observable). – Bronzato Apr 29 '13 at 13:04
  • well, this is very strange (see http://stackoverflow.com/q/8537397/866172) as any observable normally has this function. Maybe you could try with "notifySubscribers", see my updated answer – Jalayn Apr 29 '13 at 13:22
  • By combining `observable(null);` and `observable.notifySubscribers(null);` it works. I need both because `notifySubscribers` don't update data, it only notify that some data has changed. Thanks. Your help was benefic. – Bronzato Apr 29 '13 at 13:36