Sean
Sean

Reputation: 2416

JForm - Multiple Validation Rules?

I have a form (defined in XML) which is used with Joomla's JForm to handle. What I'd like to know is if it's possible to validate against multiple rules at once.

Typically, I've come to understand that Joomla's JForm accepts only one rule for validation, defined in the XML of the form:

Joomla's JForm internals also seem to suggest I can't, the following area being the only one I can find handing validation:

    // Get the field validation rule.
    if ($type = (string) $element['validate'])
    {
        // Load the JFormRule object for the field.
        $rule = $this->loadRuleType($type);

        // If the object could not be loaded return an error message.
        if ($rule === false)
        {
            throw new UnexpectedValueException(sprintf('%s::validateField() rule `%s` missing.', get_class($this), $type));
        }

        // Run the field validation rule test.
        $valid = $rule->test($element, $value, $group, $input, $this);

        // Check for an error in the validation test.
        if ($valid instanceof Exception)
        {
            return $valid;
        }
    }

This isn't wrapped in a loop, so I'm quite concerned that I can't apply multiple rules at once to a particular field.

Upvotes: 1

Views: 1415

Answers (3)

Elin
Elin

Reputation: 6770

This is a common request. There are a few possibilities. You could write your own JFormRule with more complex validation. The other is that you could programatically add an attribute to the field that runs the additional validation sort of like what Sean is advocating.

Upvotes: 2

Brian Bolli
Brian Bolli

Reputation: 1873

Are you looking for server or client side validation? Sean's answer seems to cover server side so I figured I'd add some insight into client side techniques.

You enable client side validation two ways. The first and simplest would be by adding the following to your form field definition, which would ensure any required fields are filled out to proceed.

required="true"

Second would be to add a class to the form field definition to let Joomla core know you want to validate the field and how. Joomla offers 4 validations built into the core: validate-username, validate-password, validate-numeric and validate-email.

These in and of themselves don't help you much, but the ability to create and reference custom client-side validations does. For my example we're going to ensure a check box is marked before allowing the form to submit. So in the form field definition I'll add:

class="validate-checked"

On the page where you render the form, be sure to load the JS library for validation using:

JHtml::_('behavior.formvalidation');

In addition, add the class form-validate to your form HTML element.

Add this javascript to handle the actual validation, here I have a checkbox input type with an ID of tos I'm verifying. In the setHandler method, the first parameter is the custom name I entered in the form field definition class statement, validate-checked:

<script>
window.addEvent('domready', function(){
    document.formvalidator.setHandler('checked', function(value) {
            var tos = document.getElementById('tos');
    if (tos.checked) {
        return true;
    } else {
        return false;
    }
    });
});
</script>

Now, capture the submit event and verify all core and custom validations passed before submitting the form.

Joomla.submitbutton = function(task) {
    if (task == 'user.cancel' || document.formvalidator.isValid(document.id(".myFormId"))) {
        Joomla.submitform(task, document.getElementById('myformId'));
}

You can create as many custom client-side validation scripts as you want. Inside the setHandler method you can interact with the DOM and use the passed in value parameter to determine if the field should pass, only needing to worry about returning true or false to indicate results and Joomla will handle the rest. So you can either create one complicated validation or many smaller concise validations to suit your needs.

Hope that helps...

Upvotes: 3

Sean
Sean

Reputation: 2416

This answer assumes that it is not possible to natively add multiple rules on one field.


Assuming that it is not possible to apply multiple rules to one field natively, then it may be possible to extend JForm::validateField() to enable such a feature by simply calling the validate method for each validation rule found.

// Extending class JForm

protected function validateField(SimpleXMLElement $element, $group = null, $value = null, JRegistry $input = null) {

    if($type = (string) $element['validate'])
    {
        $multiple_types = explode('|', $type);

        if(is_array($multiple_types) && $multiple_types[0] !== $type)
        {

            foreach($multiple_types as $single_type)
            {
                $result = parent::validateField($element, $group, $value, $input);

                // Validation failed, return the result and stop validating.
                if($result !== true) 
                {
                    return $result;
                }
            }

            return true;
        } 
        else 
        {
            return parent::validateField($element, $group, $value, $input);
        }
    }
}

With that example, validation rules could be structured like:

validate="rule1|rule2"

Upvotes: 0

Related Questions