Custom Rules

There are a few parts to this if you want to add custom validation well. Firstly, if using the jQuery validate functionality, ideally you want to have your custom rule validating before server side processing (as well as of course during server side processing).

As long as the following javascript is run after jQuery validate had been included, you can add as many validation methods as you like. If you have a collection of common rules it would be beneficial to have them in a separate javascript file.

See core/components/jsonformbuilder/docs/examples/JsonFormBuilder-template.php for an example of the customPhoneNum validation method.

Create a jQuery Validate method

Add a library of your own custom validation methods if you want to create your own (they could be created inline like this, or as an external JS file). Just make sure this is loaded into your template after the jQuery and jQuery Validate files are loaded, but before the form Javascript is output. If using the placeholder you would order it similar to this.

<!-- Grab the latest jQuery, or link directly from a Content Delivery Network -->
<script src="" type="text/javascript"></script>
<!-- Grab the latest jQueryValidate Plugin, or link directly from a Content Delivery Network -->
<script src="" type="text/javascript"></script>

<script type="text/javascript">
// <![CDATA[
jQuery().ready(function() {
    jQuery.validator.addMethod("customPhoneNum", function(phone_number, element, val) {
        phone_number = phone_number.replace(/\s+/g, "");
        var matchStr = '^\\(?(\\d{'+val[0]+'})\\)?[- ]?(\\d{'+val[1]+'})[- ]?(\\d{'+val[2]+'})$';
        return this.optional(element) || phone_number.match(matchStr);
    }, "Phone number invalid");
// ]]>

<!-- Set a placeholder in your template or content page that will receive any JavaScript from the form process. -->
<script type="text/javascript">
// <![CDATA[
// ]]>

The Code

You now need to create the validation method for the server side processing. You could havea bunch of these in a class and use them whenever you like. For this example, it is all coded right into the snippet.

require_once $modx->getOption('core_path',null,MODX_CORE_PATH).'components/jsonformbuilder/model/jsonformbuilder/JsonFormBuilder.class.php';

$o_fe_name      = new JsonFormBuilder_elementText('name_full','Your Name');
$o_fe_phone      = new JsonFormBuilder_elementText('phone','Phone');
$o_fe_buttSubmit    = new JsonFormBuilder_elementButton('submit','Submit Form','submit');


//Add the custom validation method to your form element by doing the following

//1. Create a custom rule.
$numBlocks = array(3,3,4);
$rule = new FormRule(FormRuleType::custom, $o_fe_phone, NULL, 'Phone number must be in format '.str_repeat("#",$numBlocks[0]).'-'.str_repeat("#",$numBlocks[1]).'-'.str_repeat("#",$numBlocks[2]));
//2. For jQuery validate to file off we need to tell it what rule to match
//3. Optionally we can pass a value to it as well if the validation method needs to know a variable (e.g. minLength, or the example in the template).

//4. Create an anonymous validate function that will be used to determine value at the server side, and specify to use this via the setCustomRuleValidateFunction method.
//$val will contain the form element value, $var will contain the contents of the param specified in step 3 above.
$func = function($val=null,$var=null){
        $phoneVal = $val;
        $foundMatches = preg_match ('/^\(?(\d{'.$var[0].'})\)?[- ]?(\d{'.$var[1].'})[- ]?(\d{'.$var[2].'})$/',$phoneVal);
            return false;
    return true;

//Finally, add the rule to the form
$a_formRules[] = $rule;

$o_form = new JsonFormBuilder($modx,'contactForm');

//Note, this is not required, you may want to not send an email and record the data to a database.
$o_form->setEmailFromName('No One');
$o_form->setEmailSubject('JsonFormBuilder Custom Validate Test');

//Set jQuery validation on and to be output
//You can specify that the javascript is sent into a placeholder for those that have jquery scripts just before body close. If jquery scripts are in the head, no need for this.

//The form HTML will now be available via
return $o_form->output();