Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add custom multiple validations with Parsley

Is it possible to add a custom multiple validation (i.e. a single validation that depends on multiple inputs) with Parsley?

I sometimes would like to validate a <form> or a section as a whole and provide an error at that level instead of at the <input> level.

For example, imagine a form with a <table> that allows the user to enter different combinations of Color and Size. Say I want to validate there are no duplicate combinations. The optimal way would be to validate row per row and look for a duplicate row above it. If duplicate rows are found, these whole rows are invalid, without any individual input being actually invalid per say. Moreover, a change in any field can make that or other row invalid.

If I try to add, say, "tr.combination" to the inputs option, the <table> won't be added the fields. Looks like the options aren't passed to the constructor so it doesn't return a ParsleyField and instead returns a generic Parsley object.

I'm even further from constructing a ParsleyFieldMultiple, as the selector is hardcoded and the code highly dependent on checkbox/radio

like image 368
Marc-André Lafortune Avatar asked Oct 19 '22 22:10

Marc-André Lafortune


1 Answers

What you're trying to accomplish can't be done natively by Parsley. Considering that it seems like a really specific situation, you may want the following solution:

  1. Instead of creating a custom validator, use Parsley events to perform that validation
  2. Based on the existence of duplicate combinations, tweak the ParsleyForm.validationResult.

This isn't the most elegant solution but I think it's the simplest one. Actually I don't think that you can find an elegant solution for this issue.

You can test this at this working jsfiddle.

// bind event after form validation
$.listen('parsley:form:validated', function(ParsleyForm) {
    // We only do this for specific forms
    if (ParsleyForm.$element.attr('id') == 'myForm') {
        var combinations = [];

        // foreach tr
        ParsleyForm.$element.find('tr').each(function() {
            var tr = $(this);

            // if there are any inputs
            if (tr.find('input').length > 0) {
                // Add a new combination based on tr's inputs
                combinations.push(tr.find('input:first').val() + '|' + tr.find('input:last').val());
            }
        });

        // sort array
        combinations = combinations.sort();

        // check if there are duplicate combinations
        for (var i = 0; i < combinations.length - 1; i++) {
            // if two combinations are equal, show message
            // and force validation result to false
            if (combinations[i + 1] == combinations[i]) {
                ParsleyForm.validationResult = false;

                $("#form-message-holder")
                    .html('There are some errors with your form')
                    .css('display', 'block');
                return false;
            }
        }

        // otherwise, validation result is true and hide the error message
        ParsleyForm.validationResult = true;
        $("#form-message-holder")
            .html('')
            .css('display', 'none');
    }
});
like image 177
Luís Cruz Avatar answered Oct 22 '22 19:10

Luís Cruz