7
votes

I'm using durandal/breeze with Knockout.

I am working on validation on my inputs with ko.validation.

Here is a classic:

<input type="text" data-bind="value: myDate, validationOptions: { errorElementClass: 'input-validation-error'}" />

.input-validation-error {
    background-color: #c75b55 !important;
}

This one works pretty well: when validation failed, the input textbox is marked in red.

Now I would like to use a bindingHandlers in place of a 'simple' value binding:

<input type="text" data-bind="dateRW: myDate, validationOptions: { errorElementClass: 'input-validation-error'}" />

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.isValid())
            if (dateFormatted)
                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);            
    }
};

With this implementation, validation works, I mean ko.validation.group is working well

var validationErrorsCount = ko.computed(function() {
    if (typeof itinerary() == 'undefined') return;
    var validationErrors = ko.validation.group(itinerary());
    return validationErrors().length;
});

But the input textbox is no more marked in red. It seems that 'validationOptions' only work with the value binding.

Any way to have my validation work?

Thanks.

3

3 Answers

13
votes

The validation framework have hooks for the value binding, you need to call

ko.validation.makeBindingHandlerValidatable("dateRW");

edit: its not undefined https://jsfiddle.net/it3xl/n7aqjor9/

2
votes

Looking at the knockout-validation.js source it calls:

makeBindingHandlerValidatable('value') to make the value binding automatically validatable.

You could try adding a call to makeBindingHandlerValidatable to register your handler:

ko.bindingHandlers.dateRW = {
    //dateRW --> the 'read-write' version used both for displaying & updating dates
    init: function (element, valueAccessor, allBindingsAccessor) {
       ...
    },
    update: function (element, valueAccessor, allBindingsAccessor) {
       ...
    }
};

ko.validation.makeBindingHandlerValidatable('dataRW');
0
votes

validationMessage binding with an empty element.

I don't wanna have the textbox marked in red.
Sometimes it's allowable to use an additional empty markup (span) with the validationMessage binding.

<input data-bind="datepickerCustom: myDate"/>
<span data-bind="validationMessage: myDate" class="validationMessage"></span>