Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout Validation not working with a DatePicker bindingHandler

So I am using Knockout Validation to validate my viewmodel and a custom knockout datepicker bindingHandler to attach a jQuery-UI datepicker to dynamically added items in my observableArray.

It seems my bindingHandler is destroying or breaking the validation rules on that field. Neither of the validation rules for the Start or End date seem to be getting enforced.

JSFiddle Link of my code

HTML code:

<form>
    <a class="btn btn-default" data-bind="click: function () { $root.addMed(); }">Add New Medication</a>

    <h6 data-bind="visible: patientMeds().length < 1">No medications entered.</h6>

    <table class="table table-condensed" data-bind="visible: patientMeds().length > 0">
        <thead>
            <tr>
                <th>Med</th>
                <th>From</th>
                <th>To</th>
                <th></th>
            </tr>
        </thead>
        <tbody data-bind="foreach: patientMeds">
            <tr>
                <td>
                    <input class="form-control" data-bind="value: MedicationID" />
                </td>
                <td>
                    <input class="form-control" data-bind="datepicker: StartDate, datepickerOptions: { changeMonth: true, changeYear: true, showButtonPanel: true }" />
                </td>
                <td>
                    <input class="form-control" data-bind="datepicker: DiscontinuedDate, datepickerOptions: { changeMonth: true, changeYear: true, showButtonPanel: true }" />
                </td>
                <td>
                    <button class="btn btn-default" data-bind="click: $parent.removeMed">Delete</button>
                </td>
            </tr>
        </tbody>
    </table>
</form>

Javascript / ViewModel code:

ko.bindingHandlers.datepicker = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var options = allBindingsAccessor().datepickerOptions || {};

        $(element).datepicker(options);

        //handle the field changing
        ko.utils.registerEventHandler(element, "change", function () {
            var observable = valueAccessor();
            observable($(element).datepicker("getDate"));
        });

        //handle disposal (if KO removes by the template binding)
        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).datepicker("destroy");
        });

    }
};

function PatientMedication(p) {
    var self = this;
    p = p || {};

    self.MedicationID = ko.observable(p.MedicationID || 1)
        .extend({
        required: {
            params: true,
            message: 'Please enter a medication'
        },
        number: true
    });
    self.StartDate = ko.observable(p.StartDate).extend({
        required: {
            params: true,
            message: 'Please enter a date'
        },
        date: true
    });

    self.DiscontinuedDate = ko.observable(p.DiscontinuedDate || '').extend({
        required: {
            params: true,
            message: 'Please enter a date'
        },
        date: true
    });
}

function MedicationViewModel() {
    var self = this;

    self.patientMeds = ko.observableArray([]);

    self.addMed = function () {
        self.patientMeds.unshift(new PatientMedication());
    };

    self.removeMed = function (med) {
        self.patientMeds.remove(med)
    };
};

var medvm = new MedicationViewModel();
ko.applyBindings(medvm);
like image 859
Brad C Avatar asked Dec 20 '22 03:12

Brad C


1 Answers

The validation plugin only hooks into the value, checked, textinput and selectedOptions bindings.

If you want to make your custom binding trigger the validations you need to call the validation.makeBindingHandlerValidatable method of the plugin and pass in the name of your custom binding:

ko.bindingHandlers.datepicker = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        //...
    }
};
ko.validation.makeBindingHandlerValidatable('datepicker');

Demo JSFiddle.

like image 136
nemesv Avatar answered Dec 24 '22 01:12

nemesv