The default validation doesnt allow the user to submit the form if one of the elements doesnt validate; Im wondering if is possible to define a 'non-blocking' validation, e.g. the user will get an alert (via javascript) but can continue, and nothing happen server-side (form_valdiate functions)

Comments

Jelle_S’s picture

You will need to solve this in a custom module. Here's how you can skip the clientside validation but still alert the errors that occured:

Assuming you only want this for one particular form:

  • Go to admin/config/validation/clientside_validation/custom-forms
  • Add your Drupal form id (e.g. article_node_form)
  • Click on 'enable' next to your newly added form id
  • Click 'edit' next to your newly added form id
  • Check 'Override default options for Error message placement'
  • Select 'Custom function' under 'Default location'
  • Enter a custom function name and remember it (eg 'cvnonblocking')
  • In you custom module implement hook_form_FORM_ID_alter and attach your custom js file e.g.:
    function cv_non_blocking_form_article_node_form_alter(&$form) {
      $form['#attached']['js'][] = drupal_get_path('module', 'cv_non_blocking') . '/js/cv_non_blocking.js';
    }
    
  • In your custom js file, on the Drupal.clientsideValidation prototype, define your custom error placement function (with the name you remembered earlier). This should just be an empty function since we don't want to display any errors.
  • Also in your custom js file, bind to the 'clientsideValidationFormHasErrors' event. In that event handler, get the validator for your form and loop through its errorMap property to get the errors for your form, then alert them and call the submit function on your DOM form element (not the jquery-wrapped element) to submit without validation
  • Your custom js file should look something like this:
    (function (Drupal, $) {
      Drupal.behaviors.cvNonBlocking = {
        attach: function(context) {
          // Define the custom error placement function with the correct name.
          Drupal.clientsideValidation.prototype.cvnonblocking = function (error, element) {
            // Do nothing, we do not want do display any errors.
          };
    
          var form_id = 'article-node-form';
          // React to a form that has errors
          $(document).bind('clientsideValidationFormHasErrors', function(e, element) {
            var $element = $(element);
            var $form = $element.is('form') ? $element : $element.closest('form');
            // Check if the form is our form
            if ($form.attr('id') === form_id) {
              // Get the validator for this form.
              var validator = $form.data('validator');
              var errors = '';
              for (var id in validator.errorMap) {
                if (validator.errorMap.hasOwnProperty(id)) {
                  errors += validator.errorMap[id] + "\n";
                }
              }
              // Alert the errors.
              alert(errors);
              // Trigger the DOM submit method to skip validation.
              $form[0].submit();
            }
          });
        }
      }
    })(Drupal, jQuery);
    

I'm not sure on how to then skip the server-side validation, I'm afraid you'll have to figure that out yourself, but this should at least get you going with the clientside part ;-)

Strae’s picture

Hi Jelle_S, the project who need this thing has a very short delivery-time so I ended up with writing a custom module to handle the validation, both clientside and serverside (I took and adapted few functions from ClientSide valdiation, like build_recurse).

For adding the validation to a field, I created a simple table with 2 cols: field machine name and validation (that is a json object, but a serialized array could do the work as well)

For the server side valdiation is pretty simple, standard form_validation hooks and so on.

For the client-side is pretty simple too; When I find a field with a validation, I simply insert the json object inside Drupal.settings.mymodule.FORM_ID.field_machine_name, and using the Drupal ajax framework it works in with ajax too

I just discovered how to stop a form ajax submit (https://drupal.org/node/1907932).

The json object I use is something like:

[
    {
        'f': 'length',
        'params': [5,10], // equivalent to length[5,10]
        'type': 'warn', // Non blocking, the user get just a warning,
        'message': 'The length of this field should be between 5 and 10 chars!'
    },
    {
        'f': 'alpha',
        'type': 'error', // Blocking, the form can not be submitted
        'message': 'Only letters allowed'
    }
]

Now im planning to use drupal's variables (drupal_variable_set and _get) becose they get cached, instead in my actual situation i query the db for every field im processing (need to find a way to optimize this)

Im using the database to store the field validation becose, even if for now I insert the validations by hand, in the future there will be a GUI for the creation of the json object.

At the moment the validation functions I have are just the few needed by this project (length, regexp, alpha, alnum, num, phone, email)

Jelle_S’s picture

Status: Active » Fixed

Thanks for sharing your solution! :-)

Strae’s picture

@Jelle_S, this is my code: http://pastebin.com/eYY16ihP , if it can help ;)

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.