Pre-Populating Repeater Fields

Hi all, I have a tricky issue/question about repeater fields…

I’m trying to pre-populate a form from entry data, that contains a set of nested repeater fields. I’ve got it working with the code below, except it doesn’t have the data properyl when submitted. I can see the problem is to do with the input field names/IDs as these are normally set as a numerical array, whereas with my prepoluated version, all instances have the same name/ID (0).

Does anyone know the right way to set the names/IDs with the correct array keys?

<?php

// Populate repeater fields
function populate_repeater_on_edit($form){
	// Check if we're editing the form entry
	if(isset($_GET['gform_post_id']) && $_GET['gform_post_id'] != ''){		
		// Get WPDB for database queries
		global $wpdb;
		// Get the post ID from the URL
		$post_id = $_GET['gform_post_id'];
		// Get the GF entry data
		$entry_id = $wpdb->get_results("SELECT * FROM $wpdb->postmeta WHERE `post_id` = $post_id && `meta_key` = '_gform-entry-id'");
		$entry_id = $entry_id[0]->meta_value;
		$entry = GFAPI::get_entry($entry_id);
		// Loop through form fields
		foreach($form['fields'] as $field){
			// If we're on our repeater field
			if($field->id == '1000'){
				// Grab details of all the labels and description to use when creating new repeater entires
				$labels = array(
					'element_label' => $field->fields[0]->label,
					'element_description' => $field->fields[0]->description,
					'facts_label' => $field->fields[1]->label,
					'facts_description' => $field->fields[1]->description,
					'facts_addButtonText' => $field->fields[1]->addButtonText,
					'facts_removeButtonText' => $field->fields[1]->removeButtonText,
					'fact_label' => $field->fields[1]->fields[0]->label,
					'fact_description' => $field->fields[1]->fields[0]->description,
					'evidences_label' => $field->fields[1]->fields[1]->label,
					'evidences_description' => $field->fields[1]->fields[1]->description,
					'evidences_addButtonText' => $field->fields[1]->fields[1]->addButtonText,
					'evidences_removeButtonText' => $field->fields[1]->fields[1]->removeButtonText,
					'evidence_label' => $field->fields[1]->fields[1]->fields[0]->label,
					'evidence_description' => $field->fields[1]->fields[1]->fields[0]->description
				);
				// Set an empty array to use for our repeater field data
				$populated_fields = array();
				// Loop through each 'Element' in our entry data
				foreach($entry['1000'] as $entry_element){
					// Create the 'Element' and add it to our array
					$element = GF_Fields::create(array(
						'type'   => 'text',
						'id'     => 1001,
						'formId' => $form['id'],
						'label'  => $labels['element_label'],
						'pageNumber'  => 1,
						'isRequired' => true,
						'defaultValue'	=>$entry_element['1001']
					));
					$populated_fields[] = $element;
					// Set an empty array to contain 'Facts' data
					$facts_data = array();
					// Loop through each 'Fact' and add it to our array
					foreach($entry_element['1002'] as $entry_facts){
						$fact = GF_Fields::create(array(
							'type'   => 'text',
							'id'     => 1003,
							'formId' => $form['id'],
							'label'  => $labels['fact_label'],
							'description' => $labels['fact_description'],
							'pageNumber'  => 1,
							'isRequired' => true,
							'defaultValue'	=> $entry_facts['1003']
						));
						$facts_data[] = $fact;
						// Set an empty array to contain 'Evidence' data
						$evidences_data = array();
						// Loop through each 'Evidence' and add it to our array
						foreach($entry_facts['1004'] as $entry_evidence){
							$evidence = GF_Fields::create(array(
								'type'   => 'text',
								'id'     => 1005,
								'formId' => $form['id'],
								'label'  => $labels['evidence_label'],
								'description' => $labels['evidence_description'],
								'pageNumber'  => 1,
								'isRequired' => true,
								'defaultValue'	=> $entry_evidence['1005']
							));
							$evidences_data[] = $evidence;
						}
						// Add the 'Evidence' data to the 'Facts' data 
						$evidences = GF_Fields::create(array(
							'type'             => 'repeater',
							'id'               => 1004, 
							'formId'           => $form['id'],
							'label'            => $labels['evidences_label'],
							'addButtonText'    => $labels['evidences_addButtonText'],
							'removeButtonText' => $labels['evidences_removeButtonText'],
							'pageNumber'       => 1,
							'fields'           => $evidences_data,
						)); 
						$facts_data[] = $evidences;
					}
					// Add the 'Facts' data to the 'Elements' data
					$facts = GF_Fields::create(array(
						'type'             => 'repeater',
						'id'               => 1002, 
						'formId'           => $form['id'],
						'label'            => $labels['facts_label'],
						'addButtonText'    => $labels['facts_addButtonText'],
						'removeButtonText' => $labels['facts_removeButtonText'],
						'pageNumber'       => 1,
						'fields'           => $facts_data,
					)); 
					$populated_fields[] = $facts;
				}
				// Add the 'Elements' data to the form
				$field->fields = $populated_fields;
			}
		}
	}
	// Return the form data
	return $form;
}
add_filter('gform_pre_render_35', 'populate_repeater_on_edit');

?>

Thanks,

Owen.

I have already replied your ticket, but I’m replying here too just for the record:

I’m sorry but repeater fields does not currently support dynamic population as mentioned the limitations section of the doc page for them: https://docs.gravityforms.com/repeater-fields/#limitations

Adding support for dynamic population is on the development teams to do list.

If you have any further question, please reply to the ticket to concentrate the conversation in one single place.

Hi,
Has there been any progress on this?
Repeaters are the number one development priority for gravity forms in my opinion.
you have such an amazing powerful form builder hard to believe this hasn’t been sorted.

There has not been any progress on this that I can report. If you would like to express your interest in the feature and show your desire for the feature, I recommend adding your notes to our Product Roadmap: https://www.gravityforms.com/gravity-forms-roadmap/

Click the blue Plus sign in the lower left, to get started. Thank you for your comments.

We have been able to get a repeater to be pre-populated. We use the gform_form_post_get_meta filter to add in the repeaters to the form, and then gform_form_args filter to pre-populate the repeater data. You have to set each repeater sub-fields to allowsPrepopulate and set the inputName. Then in the gform_form_args filter, you can set the field_values property of the args array with a multidimensional array. This array is an array of all of the inputName’s and then for each item in the repeater, you add another array value to the inputName property for each record/item.

Sample code:

foreach( $addresses as $address_item) {
    $repeater_values['contact_address_1'][]       =  $address_item['address 1'];
    $repeater_values['contact_address_2'][]       =  $address_item['address 2'];
    $repeater_values['contact_address_city'][]    = $address_item['address city'];
    $repeater_values['contact_address_postal'][]  = $address_item['address zip'];
    $repeater_values['contact_address_country'][] = $address_item['address country'];
    $repeater_values['contact_address_state'][] = $address_item['address state'];
}
args['field_values'] = $repeater_values;

Each property in $repeater_value would be the inputName from an input of the repeater. The foreach would be the values from some source to populate from. You can also make sure that the rest of the field_values are preserved if it isn’t already empty.

Maybe this can help you some. I’ve tried to set the defaultValue of the actual repeater with an array of values for the child fields, but the only way I can pre-populate is to use the field_values of the gform_form_args filter.

3 Likes

Just to add to this, if the Repeater field is NOT on the first page of the form then using the gform_form_args filter won’t work. My team spend a little while doing a deep dive down that rabbit hole this week.

You can however use the gform_pre_render filter to override the associated $_POST data for the repeater field to populate a Repeater on subsequent pages. You’d need to inspect your $_POST data to determine the correct field keys for the repeater. You can then configure it by setting those $_POST fields as an array:

$key_mapping_array = [
	'Name'             => '13',
	'Hourly Rate'      => '16',
	'Daily Rate'       => '15',
	'Fortnightly Rate' => '17',
];

foreach ( $this->get_selected_staff_members( $form ) as $staff_id ) {
	$staff = \GFAPI::get_entry( $staff_id );

	$_POST[ 'input_' . $key_mapping_array['Name'] ][] = $staff[1];
	$_POST[ 'input_' . $key_mapping_array['Hourly Rate'] ][] = $staff[2];
	$_POST[ 'input_' . $key_mapping_array['Daily Rate'] ][] = $staff[3];
	$_POST[ 'input_' . $key_mapping_array['Fortnightly Rate'] ][] = $staff[4];
}
2 Likes

Thanks so much for this, it worked perfectly!

That is odd as we have been using the gform_form_args filter to populate our repeaters and our repeaters are on the second page of the forms we have setup.

Maybe it’s an AJAX vs non-AJAX form issue? I’ll have to take a closer look at it again.

1 Like

That could be the difference. Our forms are non-Ajax forms.