0

I'm seeing unexpected behavior when attempting to validate a view model comprised of collections of validatedObservable objects; actually, nested collections.

First, let me point you to my JSFiddle that demonstrates the behavior: http://jsfiddle.net/cbono/ZTXB9/8/

My view model is an App object. It contains a single property, Services, which is a collection of Service objects. Each Service contains a Retailers property which, you guessed it, is a collection of Retailer objects. Each object is instantiated as a validatedObservable so that I can call isValid on the top level object and find any/all errors in child objects.

When I init the library, I use:

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

The only validation rule I have in effect is on Retailer objects. If the Retailer is selected and the Retailer's name is "Other" ((IsSelected() && IsOther()) === true), then the OtherDesc property is required. That's it. Otherwise, the Retailer is valid.

When I test the rule (check one of the "Other" checkboxes and leave the accompanying Description field blank), validation fails as expected. However, the view model's errors collection contains this:

  [undefined, undefined, "This field is required"]

Further, I get this error on the JS console when self.errors.showAllMessages() is called:

   Uncaught TypeError: Object function d(){if(0<arguments.length)
      {if(!d.equalityComparer||!d.equalityComparer(c,arguments[0]))d.H(),c=arguments[0],d.G();return this}b.r.Wa(d);return c} 
         has no method 'isModified' 

I'm pretty sure these two problems are related, but I haven't been able to piece together what's happening behind the scenes. It seems like when the validation library is walking the object graph, it's getting hold of objects that are not the correct type (hence no IsModified method) and thus placing a bunch of undefined's in the errors collection.

Am I not using the library as intended? I'm trying very hard to get this to work because I really like the idea of model validation. It would be much more complicated to recreate this validation in something like jquery.validate.

CBono
  • 3,803
  • 1
  • 32
  • 40

1 Answers1

2

It looks like validatedObservable's can not be nested. Leaving only App as validatedObservable solves the problem.

self.Services = ko.observableArray(
ko.utils.arrayMap(data, function (svc) {
    return new Service(svc); // unwrap
}));

//....

self.Retailers = ko.observableArray(
ko.utils.arrayMap(data.retailers, function (rtl) {
    return new Retailer(rtl); // unwrap
}));

http://jsfiddle.net/ostgals/ZTXB9/16/

Rango
  • 3,877
  • 2
  • 22
  • 32
  • You know, it drives me crazy when the solution is that simple. I wish the documentation had been more clear about correct usage of `validatedObservable`. Anyway, it works great -- thanks! – CBono Feb 12 '13 at 19:46