问题
I develop a project with Durandal/Breeze using intensive Knockout bindings.
I have a view which is using the following observable:
packing
- description
- weight
- ...
- isotopes
- name
- activity
- ...
As you can see above: my packing
observable contains an isotopes
observableArray inside. This packing
object is filled from breeze with a query.
var query = entityQuery.from('Packings')
.where('id', '==', packingId)
.expand('isotopes');
I try to set validation in place for all of this using ko.validation.
The
description
property of mypacking
observable is requiredThe
name
property of myisotopes
observableArray is required
I successfully validate on description. So whenever user clear the input field binded to description
, this one is highlighted in red. And whenever user add a new empty entity (breeze) and click on save, this one is highlighted in red.
This works thanks to this code in the save button:
var validationErrorsCount = ko.computed(function () {
if (typeof packing() == 'undefined') return;
var validationErrors = ko.validation.group(packing());
return validationErrors().length;
})
if (validationErrorsCount() > 0) {
logError('Validation failed, please check.', '', true);
ko.validation.group(packing()).showAllMessages();
return;
}
So far so good.
Now I need to validate the property name
for my isotopes
observableArray. So whenever user clear the input field binded to name
, this one is highlighted in red. It works. But the problem is whenever user add a new empty entity (breeze) of type isotope
, don't type anything for the name
input box and click on save, this one is not highlighted in red.
When I debug and inspect values I can clearly see that:
ko.validation.group(packing(), {deep:false});
did not return any invalid thingsko.validation.group(packing().isotopes(), {deep:false});
did not return any invalid things
So it seems that ko.validation did not detect my invalid inputs.
My question: how to validate my nested isotopes
observableArray when I add a new element inside?
Thanks.
UPDATE
Here is another SO post with the problem: Breeze.js & Knockout.js: translating breeze validation to knockout validation causes an 'Out of stack space' or 'Too much recursion'
Here is my 'dirty' & temporary hack (from line 4 to 9)
// Check errors on the packing entity
var validationErrorsCount = ko.validation.group(packing()).length;
// Check errors on the isotopes entities !! code below is a temporary hack
ko.utils.arrayForEach(packing().isotopes(), function (isotope) {
if (!isotope.name.isValid()) {
validationErrorsCount = validationErrorsCount + 1;
ko.validation.group(isotope).showAllMessages();
}
});
if (validationErrorsCount > 0) {
logError('Validation failed, please check.', '', true);
ko.validation.group(packing()).showAllMessages();
return;
}
Still waiting for a better way for validating my inner (nested) models.
回答1:
I do not think there is an easy way. At a certain degree of complexity, it's easier to move to an "ItemViewModel". An ItemViewModel is a view-oriented wrapper around an inner entity. It exposes carefully controlled properties designed for easier binding. I described the approach here in connection with a different problem.
I don't know if you've hit that wall.
Another thought: write a couple of custom validations for this EntityType that do the hard work of inspecting the isotopes. You'll know how to do the job "right" and efficiently in your validation method; you won't be relying on KO to walk the graph or suffer its problems with circularities.
回答2:
What if you change: ko.validation.group(packing().isotopes(), { deep:false });
to: ko.validation.group(packing().isotopes(), { deep:true });
Isn't that the point of deep?
来源:https://stackoverflow.com/questions/16192457/ko-validation-group-did-not-detect-my-errors-on-my-nested-observablearray