Client Side Field Validation

First, we will look at getting setup for validating a custom field, then we will look at implementing custom required validation for a custom field.

Custom Validation

In the below example, we are using a boilerplate JS object.

Initial Setup

First, on line 1, we define our controller (the object which will contain our custom validation).

Second, on line 4, we instantiate our controller within the document.ready jQuery hook.

var myCustomFieldController = Marionette.Object.extend({});
jQuery( document ).ready( function( $ ) {
new myCustomFieldController();
});

Instantiating inside of thedocument.ready jQuery hook is similar to using the WordPress init hook.

Hooking into Ninja Forms

With our object structure in place, we can now add listeners (hooks) to trigger our validation using the Backbone.Radio Message Bus.

Using the Backbone listenTo method, we can add hooks similar to WordPress Hooks.

For Example, on line 7 we are hooking into the form submission channel with our validate() method as the callback when the form is validating fields.

Similarly, on line 11, we are hooking into the fields channel with the same validate() method callback when a field’s model value is changed.

var myCustomFieldController = Marionette.Object.extend({
initialize: function() {
// On the Form Submission's field validaiton…
var submitChannel = Backbone.Radio.channel( 'submit' );
this.listenTo( submitChannel, 'validate:field', this.validate );
// on the Field's model value change…
var fieldsChannel = Backbone.Radio.channel( 'fields' );
this.listenTo( fieldsChannel, 'change:modelValue', this.validate );
},
validate: function( model ) {
// Custom Validation Here…
}
});

Our object’s validate() method accepts a field model object as a parameter, which we will refer to as model.

Working with the Field Model

The field model received by the validate() method is a JavaScript object containing information about that field.

We can access the field model’s properties (attributes) with the get() method, which is a getter method similar to what you would use in PHP.

Here are a few attributes available from the field model:

  • The model id is the unique id used to identify the field within the form.
  • The model type identifies the field type registered with Ninja Forms. ie Textbox
  • The model value is the value of the field, which is sent with the form submission.

Example use: model.get( ‘id ‘ )model.get( ‘type ‘ )model.get( ‘value’ )

Using these attributes we can validate our field value.

Validating the Field Model Value

Within our validate() method callback, we can verify the field type before proceeding, then get the field value to be validated.

var myCustomFieldController = Marionette.Object.extend( {
initialize: function() {
// ….
},
validate: function( model ) {
// Check the field type.
if( 'custom' != model.get( 'type' ) ) return;
// Get the field value.
var fieldValue = model.get( 'value' );
// Do Validation Here…
}
});

Custom Validation Errors

If validation fails, then we need to add an error to the field model.

In the example below, we again use the Backbone.Radio Message Bus to add our custom error.

Adding an error requires:

  • the modelID, to which the error should be added
  • the errorID, which should  be a unique string for that error
  • the errorMessage, which will be displayed on the form*.
var myCustomFieldController = Marionette.Object.extend( {
initialize: function() {
// …
},
validate: function( model ) {
// …
// Do Validation Here…
// If validation fails…
var modelID = model.get( 'id' );
var errorID = 'custom-field-error';
var errorMessage = 'This is an error message';
var fieldsChannel = Backbone.Radio.channel( 'fields' );
// Add Error
fieldsChannel.request( 'add:error', modelID, errorID, errorMessage );
}
});

* Since WordPress does not support string localization in JavaScript, error messages should be localized to the page using the WordPress wp_localize_script function, then used as a JS variable (not shown here).

Removing Custom Errors

Once the field passes your custom validation, the error needs to be removed.

Similar to adding errors, errors can be removed by passing the the modelID and the errorID.

var myCustomFieldController = Marionette.Object.extend( {
initialize: function() {
// …
},
validate: function( model ) {
// …
// Do Validation Here…
// …
// If validation passes…
var modelID = model.get( 'id' );
var errorID = 'custom-field-error';
var fieldsChannel = Backbone.Radio.channel( 'fields' );
// Add Error
fieldsChannel.request( 'remove:error', modelID, errorID );
}
});

Example Required Validation

Below is an example of custom required validation for a registered custom field.

// Create a new object for custom validation of a custom field.
var myCustomFieldController = Marionette.Object.extend( {
initialize: function() {
// On the Form Submission's field validaiton…
var submitChannel = Backbone.Radio.channel( 'submit' );
this.listenTo( submitChannel, 'validate:field', this.validateRequired );
// on the Field's model value change…
var fieldsChannel = Backbone.Radio.channel( 'fields' );
this.listenTo( fieldsChannel, 'change:modelValue', this.validateRequired );
},
validateRequired: function( model ) {
// Only validate a specific fields type.
if( 'custom' != model.get( 'type' ) ) return;
// Only validate if the field is marked as required?
if( 0 == model.get( 'required' ) ) return;
// Check if Model has a value
if( model.get( 'value' ) ) {
// Remove Error from Model
Backbone.Radio.channel( 'fields' ).request( 'remove:error', model.get( 'id' ), 'custom-field-error' );
} else {
// Add Error to Model
Backbone.Radio.channel( 'fields' ).request( 'add:error', model.get( 'id' ), 'custom-field-error', 'This is an error message' );
}
}
});
// On Document Ready…
jQuery( document ).ready( function( $ ) {
// Instantiate our custom field's controller, defined above.
new myCustomFieldController();
});