Knockout-Validation 101

As a user of KnockoutJS you quickly realise that the one thing you’re going to need is a way to validate user input. Fortunately the excellent Knockout-Validation library exists to fill that gap.

While this library does have a getting started page and some documentation, it isn’t particularly clear (at least to me!) in these pages exactly what ways you can use the library and how it works. So this post is to summarise my testing and experimentation. For brevity I will refer to the Knockout-Validation library as “KOV”.

Setup

To use KOV in the first instance you need to have both the Knockout and KOV scripts loaded in the page (in that order). KOV relies on Knockout and will complain if it’s not present.

Very Basic Introduction

KOV allows you to define validation rules that apply to a Knockout observable property, observable array and even knockout computed properties. You do this by using the extends method on an observable to define one or more rules. For example:

var viewModel = {
    name: ko.observable().extend({ required: true })
}

This is the simplest example. We have specified a rule that the name field is required.

What Actually Happened?

KOV extends our observable to apply this rule, and adds the following sub-properties to name:

Property Type Purpose
error string property the error message for this field
rules() observable array the list of rules for the property
isModified() observable set if the value has changed since original load
isValidating() computed Set if validation has started but not finished (e.g. it may be performing an asynchronous AJAX call)
isValid() computed Evaluates the rules, and returns true.

The error message is set using the default message for each rule. For example, the required extender has a default message of “This field is required.”. You can override this message by specifying different options when you call .extends().

var viewModel = { name: ko.observable().extend({

required: {

message: ‘Required!’,

params: true }

}

) }

Triggering Validation

The validation rules for an observable are triggered when an observable value is modified. In most cases for controls, this is when an input control loses focus (e.g. a textbox) or a related control is clicked (e.g. a radio button or listbox).

The validation rules are checked, and the first one to fail generates the error message.

Note: isModified(), isValid() and isValidating() are all observable or computed-observable values. That means you can bind to these values just like any other KO observable value. For example, you could bind the css for an input field to the isModified sub-property to change colour when a field is changed.

Out-of-the-Box Behaviours

In our example above we have just one field, but we have some useful behaviours added by default. The first is that the input field will have a the validation message appended after it when the user leaves the textbox.

Message Options

For simple cases this may fine. However in most cases you will want to control KOV’s behaviour using the configuration options.

You specify these using ko.init(). Note these are global options, so apply to all validations on a single page.

The option to turn off the error message inserting would be to set insertMessages to false (it is set to true by default).

If you want to keep the message, it can have a CSS class set when the error is shown. The default class is ‘validationMessage’. You can set this with the option setting errorMessageClass.

If you want fine-grain control there is also a messageTemplate setting where you can provide the ID of a text/template to use.

The last option is messagesOnModified which is set to true by default. This prevents any messages being shown until a user has modified a value. If set to false, all the errors are shown when the form is created, before the user has a change to do anything. Normally this is bad practice but there are cases when it might be useful (e.g. returning to a previously edited screen which has errors).

Element Options

Another capability (not enabled by default) is that KOV can apply a CSS class to the invalid input element. This is controlled by the options decorateElement* and errorElementClass. Setting decorateElement = true will make KOV add the class to the element’s class list. I use this to bind with a Bootstrap form to set the entire control-group’s CSS to the error state, to make it work in the Bootstrap manner.

However, note the default behaviour is to decorate just the element that failed, whereas Bootstrap forms often have a series of DIVs containing controls and you

 

Validating the Whole ViewModel

Validating single fields is useful, but most ViewModels have more than one field being validated.

This is where the KOV function validatedObservable is useful. You call ko.validatedObservable(…) and pass in your own view model – the viewmodel has following methods added:

Added Type Purpose
errors() computed observable a list of any errors on the current viewmodel
isAnyMessageShown() function returns true if any messages are show
isValid() function returns false if any validation errors are set

Important!: note that only the errors() method is a Knockout computed observable, and isAnyMessageShown and isValid are just plain functions. However the errors method does not seem to function for .subscribe.

Validation Bindings

If you don’t like the validation messages appended after the input, you can create your message placement point, and use the validationMessage binding handler: see Validation-Bindings

This displays the validation messages in the content of the bound control. It also hides the control when no messages exist: this means it can be bound to formatted control (e.g. a div with a coloured background, or popup control), and this will disappear when there is no error.

How KOV Works and Things To Watch

KOV overrides the applyBindings and the value binding handler. It adds its own validation binding handler, then calls the original value binding. This means when an observable is changed KOV knows about it and can trigger the validation.

One side affect of this is that custom binding handlers will not be validated on-screen, and you need to consider triggering the validation yourself.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s