$rule->setCustomRuleName('customPhoneNum');
//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).
$rule->setCustomRuleParam($numBlocks);
//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) {
    if (empty($val) === false) {
        $phoneVal = $val;
        $foundMatches = preg_match('/^\\(?(\\d{' . $var[0] . '})\\)?[- ]?(\\d{' . $var[1] . '})[- ]?(\\d{' . $var[2] . '})$/', $phoneVal);
        if ($foundMatches !== 1) {
            return false;
        }
    }
    return true;
};
$rule->setCustomRuleValidateFunction($func);
//Finally, add the rule to the form
$a_formRules[] = $rule;
//CREATE FORM AND SETUP
$o_form = new JsonFormBuilder($modx, 'contactForm');
$o_form->setRedirectDocument(3);
$o_form->addRules($a_formRules);
//SETUP EMAIL
//Note, this is not required, you may want to not send an email and record the data to a database.
$o_form->setEmailToAddress($modx->getOption('emailsender'));
$o_form->setEmailFromAddress('*****@*****.**');
$o_form->setEmailFromName('No One');
$o_form->setEmailSubject('JsonFormBuilder Custom Validate Test');
//Set jQuery validation on and to be output
$o_form->setJqueryValidation(true);
//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.