Knockout validation not firing with knockout custom binding

*爱你&永不变心* 提交于 2019-12-24 17:13:07

问题


I have a knockout custom binding handler for an input that I need to have validated by knockout-validation. However nothing I've done has worked. Validation is not fired. I can get validation firing on a plain ko value binding on an input bound to the same viewmodel property.

What I've found from my research (ko docs, ko-validation github docs and this SO question validationOptions not working with custom bindingHandlers amongst many others) is that you need:

ko.validation.makeBindingHandlerValidatable("yourcustombindinghandlername");

to make KO-validation take notice of your custom binding handler. I have that and I'm still getting no joy.

I've tried debugging through knockout-validation.js for both the value binding and custom binding to see what's happening differently but I can't work out what the entry point for the custom binding validation would be. My js isn't that strong TBH.

Here's a very simplified version of the code:

HTML:

<div>
<div id="vehicleQuoteDetails">
    <div>            
        <div>
            <!--with custom binding-->
            <input data-bind="vehiclemileage: quote.mileage, fieldName: 'mileage'" type="text" id="quoteMileage">
            <!--without custom binding-->
            <input data-bind="value:quote.mileage" class="form-control"/>
        </div>
    </div>
</div>
</div>

Here's the JS:

Custom Binding Handler:

ko.bindingHandlers.vehiclemileage = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        $(element).on("blur", function (evt) {
            if (evt.timeStamp !== undefined) {
                var fieldName = allBindingsAccessor().fieldName;
                bindingContext.$root.update[fieldName]($(element).val());

            }
            //return true;
        });
        //return true;
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        $(element).val(value);
        //return true;
    }
}

Viewmodel:

function JobQuoteViewModel() {
    var self = this;

    self.quote = {};

    self.getQuote = function () {

        self.quoteMapping = {
            "mileage": {
                create: function (options) {
                    return ko.observable(options.data).extend({ required: true });
                }
            }
        }

                var quoteResult = { mileage:1234 }

        ko.validation.init();
        ko.validation.makeBindingHandlerValidatable("vehiclemileage");
        self.quote = ko.mapping.fromJS(quoteResult, self.quoteMapping);
        ko.applyBindings(self);

        //$.ajax({
        //    url: "webapplication6/Home/GetQuote",
        //    type: "GET",
        //    dataType: "JSON",
        //    success: function (result) {
        //        ko.validation.init();
        //        ko.validation.makeBindingHandlerValidatable("vehiclemileage");
        //        self.quote = ko.mapping.fromJS(result.data, self.quoteMapping);
        //        ko.applyBindings(self);
        //    }
        //});
    };

    self.update = {
        mileage: function (value) {

            alert('mileage: ' + value);
        }
    }
    self.getQuote();
}

View model instantiation:

var jobQuoteVM = new JobQuoteViewModel();

And here's the fiddle for the above :https://jsfiddle.net/stevedavey/1j6vphya/

In the example I've got two inputs: one bound to a custom binding handler and one to a simple value binding. The latter is to demonstrate the validation on the plain value binding works fine.

The input on the left is the one bound to a custom binding handler and the input on the right is the value binding.

TIA for any help.


回答1:


Looks like you don't properly update the observable. You could for example use a simple computed to do so:

https://jsfiddle.net/otjg2L8z/2/

I've slightly amended your custom binding:

ko.bindingHandlers.vehiclemileage = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

        var formattedValue = ko.pureComputed({
            read: function () {
                var text = valueAccessor()();
                return text;
            },
            write: function (newValue) {
                valueAccessor()(newValue);
            }
        });
        ko.utils.registerEventHandler(element, "blur", function (evt) {
            var modelValue = valueAccessor(),
                elementValue = $(element).val();
            if (ko.isWriteableObservable(modelValue)) {
                formattedValue(elementValue);
            }    

            if (evt.timeStamp !== undefined) {
                var fieldName = allBindingsAccessor().fieldName;
                bindingContext.$root.update[fieldName]($(element).val());

            }
        });

        //return true;
    },
    update: function (element, valueAccessor, allBindingsAccessor,     viewModel, bindingContext) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        $(element).val(value);
        //return true;
    }
}


来源:https://stackoverflow.com/questions/36747210/knockout-validation-not-firing-with-knockout-custom-binding

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!