Search code examples
knockout.jsknockout-validation

Kockoutjs Validation triggers errors messages on blind


I updated ko.validation to 2.0.2 on my project for performance reasons and now all errors are showed on applyBindings.

Examples

Before: http://jsfiddle.net/rubenslopes/KHFn8/5392/

After: http://jsfiddle.net/rubenslopes/e67ho5m5/

 ko.validation.init({
     parseInputAttributes: true,
     insertMessages: true,
     grouping: {
         deep: true,
         observable: false
     }
 });


 var viewModel = function () {
     var self = this;

     self.name = ko.observable();
     self.saveLabel = ko.observable('Save');

     self.errors = ko.validation.group(self);
     self.isValid = ko.computed(function () {
         return self.errors().length === 0;
     }, self);
     self.showAllMessages = ko.computed(function () {
         return self.errors.showAllMessages();
     }, self);

     self.save = function () {
         if (self.isValid()) self.saveLabel('Saved!');
         else self.showAllMessages();
     };
 };
 ko.applyBindings(new viewModel());

Any ideas for what is happenning?


Solution

  • Your two examples are not quite the same.... if you would use the old validation plugin in your new code: http://jsfiddle.net/ex9zLfde/ it would also display the validation message initially.

    So the problem is not with the plugin version but with your actual code in your showAllMessages computed:

    self.showAllMessages = ko.computed(function () {
         return self.errors.showAllMessages();
     }, self);
    

    Because ko.computeds are first evaluated when they are declared and the self.errors.showAllMessages() call shows the error messages you will see all the errors by the time when you apply the bindings.

    To fix this you need to set the deferEvaluation on your computed to delay the initial evaluation:

     self.showAllMessages = ko.computed(function () {
         return self.errors.showAllMessages();
     }, self, {deferEvaluation : true});
    

    Demo JSFiddle.

    Or you can just call self.errors.showAllMessages() directly in your save without the using a computed:

     self.save = function () {
         if (self.isValid()) self.saveLabel('Saved!');
         else self.errors.showAllMessages();
     };
    

    Demo JSFiddle.