Using the jQuery validate plugin to check if one o

2019-08-12 01:00发布

问题:

Ok, so I am implementing the jQuery validate plugin for a Drupal 7 site. The problem I am running into is that one part of the form generates multiple checkboxes with slightly different names. Because of this there does not seem to be a direct way to check, using the validator plugin, if at least one of these checkboxes is selected.

http://docs.jquery.com/Plugins/Validation#API_Documentation

To be more specific, the user has to select one or more theme categories. These checkboxes have names like this: "field_themes[und][52]", "field_themes[und][55]", "field_themes[und][64]", and "field_themes[und][65]".

On top of this we also have a checkbox that is not related to the others that also has to be checked. That one is for agreeing to policies and such. That one is easily covered by the plugin, but I think it will make the solution for the other chekcboxes a bit trickier. I also have another set of checkboxes, but they all use the same name (Drupal is a pain at times).

So I thought about this a bit and thought that maybe I could use the submitHandler. So I came up with the below...

$('#photo-node-form').validate({
  rules: {
    'field_first_name[und][0][value]': 'required',
    'field_last_name[und][0][value]': 'required',
    'field_email_address[und][0][email]': {
      required: true,
      email: true,
    },
    'field_product_type[und]': 'required',
    'field_terms_and_conditions[und]': 'required',
  },
  messages: {
    'field_first_name[und][0][value]': 'Please enter your first name.',
    'field_last_name[und][0][value]': 'Please enter your last name.',
    'field_email_address[und][0][email]': 'Please enter a valid email address.',
    'field_product_type[und]': 'Please select a product.',
    'field_terms_and_conditions[und]': 'You must confirm that you are 18 or older and agree to the terms and conditions.',
  },
  submitHandler: function(form) {
    //Verify that at least one theme category is selected.
    var themeCatSelected = false;

    //First we have to find all of theme
    $('#photo-node-form input:checkbox').each(function(i) {
      //Make sure this is a theme checkbox
      var name = $(this).name;
      var isTheme = false;
      stristr(name, 'field_themes[und]', isTheme);

      if (isTheme && this.checked) {
        //See if this is checked
        themeCatSelected = true;
      }
    });

    if (!themeCatSelected) {
      //Do something to alert the user that is not a popup alert
      return false; //Prevent form submittion
    }

    form.submit();
  }
});

//A JS reproduction of the PHP stristr function
function stristr (haystack, needle, bool) {
  var pos = 0;
  haystack += '';
  pos = haystack.toLowerCase().indexOf((needle + '').toLowerCase());

  if (pos == -1) {
    return false;
  }
  else {
    if (bool) {
      return haystack.substr(0, pos);
    }
    else {
      return haystack.slice(pos);
    }
  }
}

So the problem I have with this is I am not sure how to put an error in the normal area for it to show the error for this submitHandler function. I'm not even sure if this is the best way to do this. Does anyone have any ideas?

Thanks!

回答1:

You'll want to do these things:

  1. Create a group for your checkboxes
  2. Create a custom validation method to ensure at least one of them is checked
  3. Add rules to your rules object for each checkbox
  4. Customize the errorPlacement function to put your error in an appropriate place

This is the code for #2 (see here for how the selector works):

$.validator.addMethod("custom_checks", function(value, element) {
    return $('#photo-node-form input[name^="field_themes[und]"]:checked').length > 0;
}, 'Please check one of these');

Here's the code for #1 and part of #3:

var tmpChecks = [], myRules = {
 'field_first_name[und][0][value]': 'required',
 'field_last_name[und][0][value]': 'required',
 'field_email_address[und][0][email]': {
  required: true,
  email: true,
 },
 'field_product_type[und]': 'required',
 'field_terms_and_conditions[und]': 'required'
};
$('#photo-node-form input[name^="field_themes[und]"]').each(function(){
   tmpChecks.push(this.name); //This is the start of #1
   myRules[$(this).attr("name")] = {
    custom_checks: true  
   }; //#3
});

And for #4, add this to your validate object:

errorPlacement: function(error, element) {
    if (element.attr("name").match(/^field_themes\[und\]/)){
   $('#checkbox_errors').html(error);
    } else {
   error.insertAfter(element);
    }
}

You end up calling validate like this:

$("#photo-node-form").validate({
    rules: myRules,
    groups: {
        checks: tmpChecks.join(' ')   //the rest of #1
    },
    errorPlacement: function(error, element) {
        if (element.attr("name").match(/^field_themes\[und\]/)){
            //I added this span after all the textboxes, you can figure this out in a more dynamic way if you prefer               
           $('#checkbox_errors').html(error); 
        } else {
           error.insertAfter(element);
        }
    }
});

​ Here is a working example on a simpler form: http://jsfiddle.net/ryleyb/nUbGk/1/