February 9, 2013: Updated to only apply validation on currently submitted page for multi-page forms.
Stop! There's a better way.
This snippet is available as a plugin with Gravity Perks, a suite of over 40 premium Gravity Forms plugins!
The snippet might look daunting but it only requires a quick copy and paste and two simple configurations to get it up and running!
<?php | |
/** | |
* Limit How Many Checkboxes Can Be Checked | |
* http://gravitywiz.com/2012/06/11/limiting-how-many-checkboxes-can-be-checked/ | |
*/ | |
class GFLimitCheckboxes { | |
private $form_id; | |
private $field_limits; | |
private $output_script; | |
function __construct($form_id, $field_limits) { | |
$this->form_id = $form_id; | |
$this->field_limits = $this->set_field_limits($field_limits); | |
add_filter("gform_pre_render_$form_id", array(&$this, 'pre_render')); | |
add_filter("gform_validation_$form_id", array(&$this, 'validate')); | |
} | |
function pre_render($form) { | |
$script = ''; | |
$output_script = false; | |
foreach($form['fields'] as $field) { | |
$field_id = $field['id']; | |
$field_limits = $this->get_field_limits($field['id']); | |
if( !$field_limits // if field limits not provided for this field | |
|| RGFormsModel::get_input_type($field) != 'checkbox' // or if this field is not a checkbox | |
|| !isset($field_limits['max']) // or if 'max' is not set for this field | |
) | |
continue; | |
$output_script = true; | |
$max = $field_limits['max']; | |
$selectors = array(); | |
foreach($field_limits['field'] as $checkbox_field) { | |
$selectors[] = "#field_{$form['id']}_{$checkbox_field} .gfield_checkbox input:checkbox"; | |
} | |
$script .= "jQuery(\"" . implode(', ', $selectors) . "\").checkboxLimit({$max});"; | |
} | |
GFFormDisplay::add_init_script($form['id'], 'limit_checkboxes', GFFormDisplay::ON_PAGE_RENDER, $script); | |
if($output_script): | |
?> | |
<script type="text/javascript"> | |
jQuery(document).ready(function($) { | |
$.fn.checkboxLimit = function(n) { | |
var checkboxes = this; | |
this.toggleDisable = function() { | |
// if we have reached or exceeded the limit, disable all other checkboxes | |
if(this.filter(':checked').length >= n) { | |
var unchecked = this.not(':checked'); | |
unchecked.prop('disabled', true); | |
} | |
// if we are below the limit, make sure all checkboxes are available | |
else { | |
this.prop('disabled', false); | |
} | |
} | |
// when form is rendered, toggle disable | |
checkboxes.bind('gform_post_render', checkboxes.toggleDisable()); | |
// when checkbox is clicked, toggle disable | |
checkboxes.click(function(event) { | |
checkboxes.toggleDisable(); | |
// if we are equal to or below the limit, the field should be checked | |
return checkboxes.filter(':checked').length <= n; | |
}); | |
} | |
}); | |
</script> | |
<?php | |
endif; | |
return $form; | |
} | |
function validate($validation_result) { | |
$form = $validation_result['form']; | |
$checkbox_counts = array(); | |
// loop through and get counts on all checkbox fields (just to keep things simple) | |
foreach($form['fields'] as $field) { | |
if( RGFormsModel::get_input_type($field) != 'checkbox' ) | |
continue; | |
$field_id = $field['id']; | |
$count = 0; | |
foreach($_POST as $key => $value) { | |
if(strpos($key, "input_{$field['id']}_") !== false) | |
$count++; | |
} | |
$checkbox_counts[$field_id] = $count; | |
} | |
// loop through again and actually validate | |
foreach($form['fields'] as &$field) { | |
if(!$this->should_field_be_validated($form, $field)) | |
continue; | |
$field_id = $field['id']; | |
$field_limits = $this->get_field_limits($field_id); | |
$min = isset($field_limits['min']) ? $field_limits['min'] : false; | |
$max = isset($field_limits['max']) ? $field_limits['max'] : false; | |
$count = 0; | |
foreach($field_limits['field'] as $checkbox_field) { | |
$count += rgar($checkbox_counts, $checkbox_field); | |
} | |
if($count < $min) { | |
$field['failed_validation'] = true; | |
$field['validation_message'] = sprintf( _n('You must select at least %s item.', 'You must select at least %s items.', $min), $min ); | |
$validation_result['is_valid'] = false; | |
} | |
else if($count > $max) { | |
$field['failed_validation'] = true; | |
$field['validation_message'] = sprintf( _n('You may only select %s item.', 'You may only select %s items.', $max), $max ); | |
$validation_result['is_valid'] = false; | |
} | |
} | |
$validation_result['form'] = $form; | |
return $validation_result; | |
} | |
function should_field_be_validated($form, $field) { | |
if( $field['pageNumber'] != GFFormDisplay::get_source_page( $form['id'] ) ) | |
return false; | |
// if no limits provided for this field | |
if( !$this->get_field_limits($field['id']) ) | |
return false; | |
// or if this field is not a checkbox | |
if( RGFormsModel::get_input_type($field) != 'checkbox' ) | |
return false; | |
// or if this field is hidden | |
if( RGFormsModel::is_field_hidden($form, $field, array()) ) | |
return false; | |
return true; | |
} | |
function get_field_limits($field_id) { | |
foreach($this->field_limits as $key => $options) { | |
if(in_array($field_id, $options['field'])) | |
return $options; | |
} | |
return false; | |
} | |
function set_field_limits($field_limits) { | |
foreach($field_limits as $key => &$options) { | |
if(isset($options['field'])) { | |
$ids = is_array($options['field']) ? $options['field'] : array($options['field']); | |
} else { | |
$ids = array($key); | |
} | |
$options['field'] = $ids; | |
} | |
return $field_limits; | |
} | |
} | |
new GFLimitCheckboxes(115, array( | |
5 => array( | |
'min' => 2, | |
'max' => 3 | |
), | |
13 => array( | |
'max' => 3 | |
) | |
)); |
How do I install this snippet?
Just copy and paste the code into your theme’s functions.php file.
Do I need to modify this snippet to work with my form?
This snippet now uses a class format. This means you can more easily use it on multiple forms! To instantiate this class you will need to know the form ID, field ID and minimum/maximum number of checkboxes which should be allowed/enforced for that field. It will look something like this:
new GFLimitCheckboxes(115, array( | |
5 => array( | |
'min' => 2, | |
'max' => 3 | |
) | |
)); |
In template form:
new GFLimitCheckboxes(FORM_ID, array( | |
FIELD_ID => array( | |
'min' => MIN_NUMBER, | |
'max' => MAX_NUMBER | |
) | |
)); |
You can specify multiple checkbox fields on a specific form like so:
new GFLimitCheckboxes(115, array( | |
5 => array( | |
'min' => 2, | |
'max' => 3 | |
), | |
13 => array( | |
'max' => 3 | |
) | |
)); |
Finally, you can apply this functionality to multiple forms:
new GFLimitCheckboxes(115, array( | |
5 => array( | |
'min' => 2, | |
'max' => 3 | |
), | |
13 => array( | |
'max' => 3 | |
) | |
)); | |
new GFLimitCheckboxes(38, array( | |
2 => array( | |
'min' => 5, | |
'max' => 5 | |
) | |
)); |
And that’s it!
input[type="checkbox"]:disabled + label { color: #999; }
Did this resource help you do something awesome with Gravity Forms? Then you'll absolutely love Gravity Perks; a suite of 39+ essential add-ons for Gravity Forms with support you can count on.
Does not work. Code snippet plugin throes error “Uncaught Error: Class “GFLimitCheckboxes” not found in ………/public_html/wp-content/plugins/code-snippets/php/admin-menus/class-edit-menu.php(248) : eval()’d code:1…….
Directly adding this snippet in functions.php causes my entire site to crash
nvm it work now
Hi Razi
Glad you were able to figure it out.
Cheers,
Is there anything similar to Multi-select?? I have a multi-select with 5 options, and I want the user to be able to ONLY choose 2 options.
Hi Haya,
We have an experimental snippet that you can use to limit a Multi-Select field.
You can use our free GF Custom Javascript plugin to add the javascript snippet to the form.
I hope this helps.
Best,
Any way to take the markings of the entire form and not of independent fields?
Hi Guillermo,
I’m not sure if I’m tracking, but if you want to span the limits across multiple fields, this is supported in the perk version of the plugin.
The snippet works great. One question is if the user clicks a box now, if they want to switch they have to un-click the current before they can switch. Is there a way to allow the user to click and have it automatically switch?
Thanks!
Thanks! Hmm, this is a good question. From what I understand as you mentioned is not currently supported. If you have a Gravity Perks license, can you get in touch with us via our support form?
Best,
I was using the code snippet, not a perk. I figured it had something to do with not disabling the other options when one is clicked?
Jonathan,
The behavior you are experiencing is by design. If you only want to let the user select one option, you can use a Radio Buttons field instead 🙂.
Best,
Unchecking boxes doesn’t appear to be making the other boxes enabled again in GF 2.5.16. Any ideas?
Hi Cory,
I am unable to recreate the issue on my end. Unchecking boxes is enabling disabling boxes with GF 2.5.16. If you have a Gravity Perks license, reach out via the support form so we can assist you further with this.
Works a treat for me on GF 2.5, only issue I currently have is that jQuery is throwing a console error, not entirely sure why as jQuery is loaded before this script in my functions.php
Hi Scott,
I am unable to recreate the issue on my end. It works as expected without a JQuery error. I’ll suggest you run a Theme/plugin conflict test to check if another plugin or code is causing this. If you have a Gravity Perks license you can get in touch with us via support form so we can assist you further with this.
Best,
This no longer works with Gravity Forms 2.5!
Hi Chad,
I’m unable to recreate the issue when I test on GF 2.5. It works as expected.
We recommend purchasing the Perk version of this snippet. Not only does it offer more features and ease of use, it also includes support.
Just wondering if this code be used to set a limit for the total items checked in a combination of three fields? So limit of 5 total for Field1+Field2+Field3…
Hi Katie, not in the snippet, but spanning limits across multiple checkbox fields is available in the Perk version.
GP Limit Checkboxes