Search code examples
javascriptknockout.jsknockout-validation

KnockoutJS Validation template and multi models


I have two pages, the first is a login page, simple :

Model KnockoutJs

function Login(){
   var self=this;
   self.email = ko.observable().extend({ email: true, required: true });
   self.password = ko.observable().extend({ required: true});
}

Model Binding

$(function () {
  ko.validation.configure({
    insertMessages: true,
    decorateElement: true,
    errorElementClass: 'validation',
    messageTemplate: "ValidationTemplate",
    errorsAsTitle: false
  });
  var login = new Login();
  ko.applyBindings(login);
});

Template Definition

<script type="text/html" id="ValidationTemplate">
    <span data-bind="attr: { error: field.error }, 
    visible: field.isModified() && !field.isValid(), 
    event: { mouseover: layout.errorTooltip }" 
    class="glyphicon glyphicon-exclamation-sign f-validation-message"></span>
</script>

Everything works fine, the little icon appears over the input which gets red borders.

Then the other page, with models hierarchy :

Model KnockoutJs Parent

function Parent()
{
  var self=this;
  self.child= new Child();
}

Model KnockoutJs Child

function Child()
{
  var self=this;
  self.val1= ko.observable().extend({ required: true });
  self.val2= ko.observable().extend({ required: true });
}

Model Parent Binding

$(function () {
  ko.validation.configure({
    insertMessages: true,
    decorateElement: true,
    errorElementClass: 'validation',
    messageTemplate: "ValidationTemplate",
    errorsAsTitle: false
  });
  var parent= new Parent();
  ko.applyBindings(parent);
});

The inputs are in this case included in a with block

<div data-bind="with:$root.child">
...
</div>

The validation template is the same.

So, the icon does not appear but the borders, yes.

When I check the code, KnouckoutJs did not "spread" the template on each input.

The only difference is the multi models system, but not sure how it impacts the binding?

Thank you for your help.

Yoann


Solution

  • Ok, I found the problem, it was not linked at all with the multi model or validation template.

    I was binding data like follow :

    //data: JS object
    self.obsProp(ko.mapping.fromJS(data));
    self.obsProp().value1.extend({required:true});
    self.obsProp().value2.extend({required:true});
    

    WRONG Way, the correct way to map the data with validation :

    var validationMapping = {
      value1: {
       create: function(options) {
          return ko.observable(options.data).extend( {required: true} );
           }
        },
      value2: {
       create: function(options) {
          return ko.observable(options.data).extend( {required: true} );
           }
        }
    };
    self.obsProp(ko.mapping.fromJS(data,validationMapping));
    

    And everything works fine.

    Thanks :)