Knockout Mapping Validation
Asked Answered
A

2

20

I'm trying to attach validation to a mapped view. I'm using Knockout Mapping and Validation plugins. Pseudo-models:

Person {
    int Id;
    string Name;
    Book[] Books;
}

Book {
    int Id;
    string Name;
}

Javascript:

function viewModel() {
    var self = this;
    self.persons = ko.observableArray();

    // persons are retrieved via AJAX...
    ko.mapping.fromJS(persons, {}, self.persons);
}

jQuery(function( $ ) {
    ko.applyBindings(new viewModel());
});

How can I extend persons observableArray to set validation rules and message? I need to validate both persons and books sub-array properties. I've found only examples that use explicit model setting, without automatic mapping, something like:

Name: ko.observable().extend({ required: true })

Then I'll need to set ko.validatedObservable, isValid and validation.init, but I really don't know how to handle/organize this. Can you please provide some help?

Ardel answered 18/12, 2012 at 12:48 Comment(0)
A
30

I have found at least two ways to supply validations to model or view model objects that are created via the ko.mapping plugin:

  1. Use the mapping options to attach the validation rules when certain properties are created
  2. HTML5 attributes. This is only supported for some validations (i.e. required, pattern). See the documentation for the Knockout-Validation plugin for details

The above two techniques can also be combined. See the following fiddle for an example.


1. Using Mapping Options

The Knockout Mapping plugin allows the creation of certain properties on mapped objects to be customized. Taking advantage of this functionality, you can override the default behavior of the plugin and add validation for your mapped properties. Below is an example

HTML

<input data-bind="value: name" />


Javascript

var data = { name: "Joe Shmo" };

var validationMapping = {
    // customize the creation of the name property so that it provides validation
    name: {
        create: function(options) {
            return ko.observable(options.data).extend( {required: true} );
        }
    }
};

var viewModel = ko.validatedObservable(ko.mapping.fromJS(data, validationMapping));
ko.applyBindings(viewModel);


2. HTML5 Attributes

The Knockout Validation plugin supports a limited set of HTML5 validation attributes that can be used in your HTML controls. However, using them requires enabling the parseInputAttributes option. Here is a simple example:

HTML

<input data-bind="value: name" required />


Javascript

// this can also be configured through the "validationOptions" binding (https://github.com/ericmbarnard/Knockout-Validation/wiki/Validation-Bindings)
ko.validation.configure({
    parseInputAttributes: true
});

var data = { name: "Joe Shmo" };

var viewModel = ko.validatedObservable(ko.mapping.fromJS(data));
ko.applyBindings(viewModel);
Alcoholic answered 2/1, 2013 at 3:13 Comment(1)
you could also include the ability to extend inside the data-bind. Like the following data-bind="value: name.extend({ required: true, email: true })"Twowheeler
W
4

Another way is to extend the observable after it has mapped.

function viewModel() {
    var self = this;
    self.persons = ko.observableArray();

    // persons are retrieved via AJAX...
    ko.mapping.fromJS(persons, {}, self.persons);


    self.Name.extend({ required: true });
}
Wicketkeeper answered 12/3, 2014 at 21:8 Comment(2)
Looks like something madness. How your magic works? The self.Name prop of viewModel should be undefined.Hispanic
This concept works fine for me, can't say anything about this exact example though.Kornegay

© 2022 - 2024 — McMap. All rights reserved.