Eliminating Options in a Gravity Form

For those of you using WordPress, GravityForms can be a real godsend. GravityForms is a premium plugin that makes it extremely simple to create forms on your website. However, there are a few features that aren’t quite built out the way they probably should be, yet.

One of those features is the ability to stop people from submitting forms with duplicate values. While this feature is extremely useful the way it’s currently implemented when it comes to duplicate entries for people’s names, email addresses, etc., it’s not overly useful when it comes to select elements, radio buttons and checkboxes. As it is currently implemented, all of the options are still available for the user to select when filling out the form, but when they submit the form, they get an error message indicating the option has already been selected.

With the use of some GravityForms filters, though, you can make things slightly more usable.

In my particular instance, I wanted a group of radio buttons to be available, and I only wanted one person to be able to select each option (the form is a registration form for a party; and the radio buttons are items that the attendees are volunteering to bring to the party with them).

I set up the form with radio buttons, checked the “Enable Values” checkbox and the “No Duplicates” checkbox for that field (along with the “Required” checkbox), gave each radio button a unique value, then saved the form. As far as setting up the form, that’s all I needed to do. The next steps have to be taken outside the scope of the form.

In my case, it’s helpful to keep all options visible on the form, but make it so that the options that have already been chosen can’t be selected. Either way, the basic steps are the same.

For my purposes, I found it simplest to implement these changes as a mu-plugin, but there’s no reason you can’t implement the same functionality using your theme’s functions.php file, or even writing your own plugin. Since this particular implementation is extremely temporary (it only needs to be in place for a week), there was no need for me to write a full-fledged plugin or to even modify my theme. You can take whichever route makes the most sense for your implementation.

To start with (since I was taking the mu-plugin route), I hooked into the plugins_loaded action to make sure GravityForms had been instantiated before I did anything. That looks like:

add_action( 'plugins_loaded', 'jwsf_gform_filters' );
function jwsf_gform_filters() {
	if ( ! is_admin() )
		add_filter( 'gform_field_content', 'jwsf_form_choices', 1, 5 );
}

Basically, that code just tells WordPress to wait until the plugins have been loaded, then hooks into the gform_field_content filter to filter out the choices that have already been selected.

Next, I wrote the jwsf_form_choices function that looks something like:


function jwsf_form_choices( $content, $field, $value, $lead_id, $form_id )
{
  /* Check to make sure we're on the right site
  Only necessary if you're using multisite 
  Change the "1" to the ID of your site
  */
  global $blog_id;
  if ( 1 !== (int) $blog_id ) return $content;

  /* Check to make sure we're loading the right form 
  Change the "2" to the ID of the form you're modifying
  */
  if ( 2 !== (int) $form_id ) return $content;

  /* Check to make sure this is the field we want to filter
  Change the "3" to the appropriate field ID
  */
  if ( 3 !== (int) $field['id'] ) return $content;

  /* Retrieve a list of the options that were already selected */
  global $wpdb;
  $tablename = $wpdb->prefix . 'rg_lead_detail';

  /* Change the "2" to the ID of your form
  Change the "3" to the ID of the field
  */
  $values = $wpdb->get_col( $wpdb->prepare( "SELECT value FROM $tablename WHERE form_id=%d AND field_number=%d ORDER BY lead_id", 2, 3 ) );

  /* Loop through all of the options available in this field
  If that choice has already been chosen by someone else, 
  add a "readonly" and "disabled" attribute to the input, 
  and make the label strikethrough
  */

  foreach ( $field['choices'] as $k => $f ) {
    if ( ! in_array( $f['value'], $values ) ) continue;

    $content = str_replace( array( "value='{$f['value']}'", "for='choice_{$field['id']}_$k'" ), array( "readonly disabled value='{$f['value']}'", "style='text-decoration: line-through' 'choice_{$field['id']}_$k'" ), $content );
  }

  /* Return the filtered content of the form field */
  return $content;
}

There are a few areas in the code above where you need to make your own modifications (your blog’s ID within your multisite installation, the ID of the form as indicated by GravityForms, the ID of the field within that specific GravityForm, etc.). Also, as mentioned above, this code simply disables the radio buttons for items that have already been selected, and then adds some CSS to make the label strikethrough. If you want to actually remove the options from the form so they don’t show up at all, you’ll probably need to run a regexp or something to actually delete that portion of the content.

One Response

  • mike

    So I took your code and placed it into the bottom of my functions.php

    I changed the id’s and table names, not sure if those are right i just have general gf tables

    add_action( 'plugins_loaded', 'jwsf_gform_filters' );
    function jwsf_gform_filters() {
    	if ( ! is_admin() )
    		add_filter( 'gform_field_content', 'jwsf_form_choices', 1, 5 );
    }
    function jwsf_form_choices( $content, $field, $value, $lead_id, $form_id ) {
    	/* Check to make sure we're on the right site
    	   Only necessary if you're using multisite 
    	   Change the "1" to the ID of your site */
    	global $blog_id;
    	if ( 1 !== (int) $blog_id )
    		return $content;
    	
    	/* Check to make sure we're loading the right form 
    	   Change the "2" to the ID of the form you're modifying */
    	if ( 18 !== (int) $form_id )
    		return $content;
    	
    	/* Check to make sure this is the field we want to filter
    	   Change the "3" to the appropriate field ID */
    	if ( 1 !== (int) $field['id'] )
    		return $content;
    	
    	/* Retrieve a list of the options that were already selected */
    	global $wpdb;
    	
    	/* Change the "2" to the ID of your form
    	   Change the "3" to the ID of the field */
    	$values = $wpdb->get_col( $wpdb->prepare( "SELECT value FROM wp_rg_form_meta WHERE form_id=%d AND field_number=%d ORDER BY display_meta", 18, 1 ) );
    	
    	/* Loop through all of the options available in this field
    	   If that choice has already been chosen by someone else, 
    	   add a "readonly" and "disabled" attribute to the input, 
    	   and make the label strikethrough */
    	foreach ( $field['choices'] as $k => $f ) {
    		if ( ! in_array( $f['value'], $values ) )
    			continue;
    		
    		$content = str_replace( array( "value='{$f['value']}'", "for='choice_{$field['id']}_$k'" ), array( "readonly disabled value='{$f['value']}'", "style='text-decoration: line-through' 'choice_{$field['id']}_$k'" ), $content );
    	}
    	
    	/* Return the filtered content of the form field */
    	return $content;
    }
    

    Any chance you can tell me why this isn’t working, also I’m, using a drop down

    thanks