cactusboat
cactusboat

Reputation: 766

How to dynamically populate Gravity Forms select (dropdown) menu items from Google Sheets data

I'm trying to dynamically populate the options available for selection in a dropdown menu using data from google sheets. The data is located on column A (A2:A4 at the moment, but this is subject to change) and will include the names of available employees.

So if:

   A
1 name 
2 jack 
3 Bob
4 John

I need these 3 names to dynamically be available for selection in a dropdown menu within gravity forms. I also need the flexibility allowing there to be more or less names whenever an employees availability changes.

I've been trying to put something together using the gravity forms documentation, as well as taking bits and pieces from snippets I've found on github. This is what I have so far, but it is giving me a critical error:

$location_form_id = [FORM ID HERE];
add_filter( 'gform_pre_render_'.$location_form_id, 'populate_posts' );
add_filter( 'gform_pre_validation_'.$location_form_id, 'populate_posts' );
add_filter( 'gform_pre_submission_'.$location_form_id, 'populate_posts' );
add_filter( 'gform_pre_submission_filter_'.$location_form_id, 'populate_posts' );
add_filter( 'gform_admin_pre_render_'.$location_form_id, 'populate_posts' );

  function populate_posts($form){
      
      foreach($form['fields'] as &$field){
          
        if($field->id != [FIELD ID HERE] ) {
           continue;
            
            // Hook into Google Spreadsheets //
            $url = 'http://spreadsheets.google.com/feeds/list/[SPREADSHEET ID HERE]/od6/public/values?alt=json';
            $file = file_get_contents($url);
            
            $json = json_decode($file);
            $rows = $json->{'feed'}->{'entry'};
            
            $names = array();
            
            foreach($rows as $row) {
                $name = $row->{'gsx$name'}->{'$t'};
                    $names[] = $name;
            }
    
        foreach($names as $single_name){
                $choices[] = array('text' => $single_name, 'value' => $single_name );
            }
            
         $field['choices'] = $choices;
          
      }
     
      return $form;
  }

Upvotes: 2

Views: 5326

Answers (2)

Jan Bakalar
Jan Bakalar

Reputation: 1

Thank you for this great example. Initially, it did not work for me until I realized that the 'name' is the heading (name) of the column and is hard-coded - I modified that. I was also missing the ability to browse between lists, so I added a variable for that.

Lastly, if your side is running on WordPress, I recommend using the 'Code Snippets' plugin instead of directly adding code into the functions.php - it is cleaner + will not stop working if your theme is modified/changed.

See below:

$location_form_id = '21';
add_filter( 'gform_pre_render_'.$location_form_id, 'populate_posts' );
add_filter( 'gform_pre_validation_'.$location_form_id, 'populate_posts' );
add_filter( 'gform_pre_submission_filter_'.$location_form_id, 'populate_posts' );
add_filter( 'gform_admin_pre_render_'.$location_form_id, 'populate_posts' );


function populate_posts( $form ) {

    //the select feild id you want the names to load
    $field_ID = 'FIELD_ID_HERE';
    //your g sheet ID
    $gSheet_form_ID = 'SHEET_ID_HERE';
    // which column to scan - what is the heading name
    $column_name = 'COLUMN_HEADING_NAME_HERE';
    $placeholder = 'YOUR_PLACEHOLDER_HERE';
    $list_number = '1';


    //get data
    $url = 'https://spreadsheets.google.com/feeds/list/'.$gSheet_form_ID.'/'.$list_number.'/public/values?alt=json';
    
    $file = file_get_contents($url);
    $json = json_decode($file);
    $rows = $json->{'feed'}->{'entry'};


    //get all the same from sheet
    $names = array(); //store names in this array
    foreach($rows as $row) {
        $name = $row->{'gsx$'.$column_name}->{'$t'};
        array_push($names, $name); //push data
    }
    
    //Go through each form fields
    foreach ( $form['fields'] as $field ) {
        //check if field type is a select dropdown and id is correct
        if ( $field->type == 'select' && $field->id == $field_ID) {
            //add name and value to the option
            foreach($names as $single_name){
                $choices[] = array('text' => $single_name, 'value' => $single_name );
            }
            //Add a place holder
            $field->$placeholder;
            //Add the new names to the form choices
            $field->choices = $choices;
            // Print out the contents of the array (troubleshooting only)
            //echo '<pre>'; print_r($choices); echo '</pre>';
        }
    }
    return $form; //return form
}

What can still be improved?

  1. The URL used for retrieving the data via Google Sheets API is using API v3, which will be deprecated on June 8th, 2021. If anyone has thoughts on how to improve the code for APIv4, then please let us know!

  2. If you are checking for a cell that is in a column that is 'shorter' than another one, you will end up with empty values in the array. There should be a check against empty values in the code (should be pretty simple to add).

Upvotes: 0

Always Helping
Always Helping

Reputation: 14570

You need to use few filters given by gravity forms to achieve this. Only four filters are required.

  1. gform_pre_render_
  2. gform_pre_validation_
  3. gform_pre_submission_filter_
  4. gform_admin_pre_render_

You need to get the loop through all the fields of your form id XX and check whether the field you are selecting is an actual dropdown field means a select field.

To push all the new found in the sheets we can use array_push method and then loop through that array to get all the names that were stored.

You can also add a placeholder if you want to to your select field and lastly just the return the $form

In the below code just add your own $form_id, select $feild_id and $gSheet_form_ID .

Add this code your active theme functions.php file. (Code tested and works)

$location_form_id = '62';
add_filter( 'gform_pre_render_'.$location_form_id, 'populate_posts' );
add_filter( 'gform_pre_validation_'.$location_form_id, 'populate_posts' );
add_filter( 'gform_pre_submission_filter_'.$location_form_id, 'populate_posts' );
add_filter( 'gform_admin_pre_render_'.$location_form_id, 'populate_posts' );
function populate_posts( $form ) {

    //the select feild id you want the names to load
    $field_ID = '2';
    //your g sheet ID
    $gSheet_form_ID = 'your_public_google_sheet_id';

    //get data
    $url = 'https://spreadsheets.google.com/feeds/list/'.$gSheet_form_ID.'/public/values?alt=json';
    $file = file_get_contents($url);
    $json = json_decode($file);
    $rows = $json->{'feed'}->{'entry'};

    //get all the same from sheet
    $names = array(); //store names in this array
    foreach($rows as $row) {
        $name = $row->{'gsx$name'}->{'$t'};
        array_push($names, $name); //push data
    }
    
    //Go through each form fields
    foreach ( $form['fields'] as $field ) {
        //check if field type is a select dropdown and id is 2
        if ( $field->type == 'select' && $field->id == $field_ID) {
            //add name and value to the option
            foreach($names as $single_name){
                $choices[] = array('text' => $single_name, 'value' => $single_name );
            }
            //Add a place holder
            $field->placeholder = 'Select a Name';
            //Add the new names to the form choices
            $field->choices = $choices;
        }
    }
    return $form; //return form
}

Working Select Field Preview

enter image description here

Upvotes: 2

Related Questions