Vlidating custom binding

by Jorge Bustos Pereda

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-debug.js"></script>
<input type="text" data-bind="value: name, required: 'Name required'">
<span data-bind="visible: name.hasError, text: name.requiredMessage"></span>
<br/>
<input type="text" data-bind="value: age, required: 'Age required'">
<span data-bind="visible: age.hasError, text: age.requiredMessage"></span>

JavaScript

ko.bindingHandlers.required = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // This will be called when the binding is first applied to an element
        // Set up any initial state, event handlers, etc. here
        console.log('Init', element);
        var valueObs = allBindings.get('value');
        valueObs.hasError = ko.observable(false);
        valueObs.requiredMessage = ko.observable(ko.unwrap(valueAccessor()));
        valueObs.firstTime = true;
        $(element).blur(function() {
            console.log('Blur');
            valueObs.hasError(!valueObs());
        });
    },
    
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // This will be called once when the binding is first applied to an element,
        // and again whenever any observables/computeds that are accessed change
        // Update the DOM element based on the supplied values here.
        var valueObs = allBindings.get('value');
        console.log('value: ', valueObs());
        if (valueObs.firstTime) {
            valueObs.firstTime = false;
            return;
        }
        valueObs.hasError(!valueObs());
    }
};

var vm = {
    name: ko.observable(""),
    age: ko.observable("")
};

ko.applyBindings(vm);