How to validate an array?
Asked Answered
R

2

8

I am trying to use knockout validation lib to validate an array of objects. It is not straightforward to me how to form a validation group for an array of observables. The only way I managed to make it work is like this (JSFIDDLE included):

var Note = function () {
    var self = this;
    self.name = ko.observable().extend({ required: true });
};

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

    self.notes = ko.observableArray([new Note(), new Note()]);

    self.validatedObservables = function() {
        var arr = [];
        ko.utils.arrayForEach(self.notes(), function(note) {
            arr.push(note.name);
        });
        return arr;
    };

    self.errors = ko.validation.group(self.validatedObservables());

    self.submit = function () {
        if (self.errors().length != 0) {
            self.errors.showAllMessages();
        }
    };

};

ko.applyBindings(new viewModel());

It seems like my approach is unnecessarily verbose. According to the source code you can simply pass an observable to ko.validation.group:

self.errors = ko.validation.group(self.notes());

But this doesn't work.

Ridenhour answered 7/6, 2012 at 17:7 Comment(0)
H
14

There is a configuration option for the grouping to be deep (recursive). It can be set either globally with ko.validation.init( { grouping: { deep: true } } ) or in the group call itself, e.g.: self.errors = ko.validation.group( self.notes(), {deep: true} );

Updated fiddle here: http://jsfiddle.net/KHFn8/4116/

BTW, the way you did it could be written in much shorter form:

self.errors = ko.validation.group(
    ko.utils.arrayMap(self.notes(), function(note) { return note.name }));

Edit: My fiddle no longer works with the latest version of KO validation. Here is the same fiddle using the latest version at the time I gave the answer (June 2012): http://jsfiddle.net/KHFn8/4117/

Hafer answered 7/6, 2012 at 19:27 Comment(4)
Great, man, you saved be a day! There's just one more thing. It works fine, but if you add another instance to an array later, it is not included in the group. Have a look at this fiddleRidenhour
What I like about knockout is that it does not have magic that stands on your way. Again, I solved my problem. The code is verbose but works - dynamically added items now added to validation. Fiddle.Ridenhour
Jim G, it worked with the latest version at the time I answered this. Edited the answer to reflect this.Hafer
@antishok: Outstanding. Upvoting to reflect this. Thanks.Oriole
E
2

I have to low reputation to comment. So here comes another answer. The answer with provided fiddles by antishok seams to not be working anymore. (The link to knockout.js was broken, but even after fixing that and adding a working link to knockout 3.0 it still was not working)

I added ko.computed around the ko.validation.group() and got it working that way.

self.errors = 
    ko.computed(function() {
        return ko.validation.group(self.notes(), { deep: true })});

http://jsfiddle.net/bezFR/17/ (Updated)

I'm guessing there is a better way to do this, but for now it solves my problem, and i'm looking forward to be corrected/seeing a better solution :)

Ettore answered 5/11, 2013 at 13:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.