Introduction
Being able to dynamically populate the values in a select (aka drop down) field is fairly common requirement for product selection forms, product option forms, or any form that requires earlier submissions to drive choices in a latter collection field.
This walkthrough will teach you how to configure a specific example of this population, using custom code to present a list of existing posts as options in the drop down.
Third Party Options
If you are not keen on custom code, or require more complex capabilities, check for third party solutions across popular WordPress Plug-In repositories, and in our very own Community Add-On Library.
Make sure you don’t miss the Add-On Populate Anything, a fully-featured offering from one of our Certified Developers, GravityWiz.
Custom Code Approach
The premise for this walkthrough is that we want to populate the options in a Gravity Form select field with all of the posts currently published on the site. There are a variety of reasons for wanting to do this, but in this example, we just want to know what the user’s favorite post is.
IMPORTANT: For obvious reasons, dynamic population can’t run when the page where your form is embedded is cached. This is not a Gravity Forms limitation but a consequence of using caching.
The Code
add_filter( 'gform_pre_render_51', 'populate_posts' );
add_filter( 'gform_pre_validation_51', 'populate_posts' );
add_filter( 'gform_pre_submission_filter_51', 'populate_posts' );
add_filter( 'gform_admin_pre_render_51', 'populate_posts' );
function populate_posts( $form ) {
foreach ( $form['fields'] as &$field ) {
if ( $field->type != 'select' || strpos( $field->cssClass, 'populate-posts' ) === false ) {
continue;
}
// you can add additional parameters here to alter the posts that are retrieved
// more info: http://codex.wordpress.org/Template_Tags/get_posts
$posts = get_posts( 'numberposts=-1&post_status=publish' );
$choices = array();
foreach ( $posts as $post ) {
$choices[] = array( 'text' => $post->post_title, 'value' => $post->post_title );
}
// update 'Select a Post' to whatever you'd like the instructive option to be
$field->placeholder = 'Select a Post';
$field->choices = $choices;
}
return $form;
}
This code should be pasted in your theme’s functions.php file.
The Hooks
Using the gform_pre_render filter allows us to modify the form right before it is displayed. This is really useful, especially when you are looking to display content that will be constantly changing. In our case, this saves us the time and hassle of having to update our drop down of posts every time we add a new post. In addition you should use the gform_pre_validation, gform_pre_submission_filter and gform_admin_pre_render filters as well.
add_filter( 'gform_pre_render_51', 'populate_posts' );
add_filter( 'gform_pre_validation_51', 'populate_posts' );
add_filter( 'gform_pre_submission_filter_51', 'populate_posts' );
add_filter( 'gform_admin_pre_render_51', 'populate_posts' );
This line tells Gravity Forms to filter the $form object through the populate_posts function every time the form with ID of 51 is displayed. You should update the 51 here to the ID of your form.
Next, let’s create a populate_posts function to modify our form.
Custom Filter Function
In this example, our custom filter function is titled “populate_posts”. Since we told Gravity Forms to call this function from the gform_pre_render filter, Gravity Forms will also send the $form object as a parameter to this function. This means we can modify the $form object with this function and then return our changes at the end of the function.
Looping Through the Fields
foreach ( $form['fields'] as $field ) { ... }
Since we have the $form object, let’s loop through the fields in the form and find the field(s) that we’d like to modify.
if ( $field->type != 'select' || strpos( $field->cssClass, 'populate-posts' ) === false ) {
continue;
}
Given our premise, we only want to modify fields that are select (drop down) fields AND have a CSS class titled “populate-posts”. We could check for the field ID instead of a CSS class; however, if we ever change our form we’d have to update the code to match the new field ID. Using a CSS class to identify our desired field allows us to manage which field should be targeted right from the Gravity Forms admin.
If the current field we are at in the loop is not a select OR does not have our designated CSS class, we simply skip that field and move on to the next.
Get the Posts
Now it’s time to get an array of all the posts to display in our drop down.
$posts = get_posts( 'numberposts=-1' );
get_posts() is a WordPress function that returns an array of posts based on the parameters you provide it. For more information on how to modify which posts are returned, read here.
$posts = get_posts( 'post_type=event&numberposts=-1' );
Creating an Array of Choices
The way Gravity Forms handles fields with multiple options (such as a select field) is with a “choices” property for the field which contains an array of “options”. Each option consists of:
- a “text” property (which is what the user will see in the drop down)
- a “value” property (which is what will be recorded by Gravity Forms)
- an “isSelected” property (which is used to indicate whether the option is currently selected or not)
- and a “price” property (which only applies to pricing fields)
In our scenario, we are only concerned with the “text” and “value” properties.
$choices = array();
The first thing we do is create an array to store all of our options.
foreach ( $posts as $post ) {
$choices[] = array( 'text' => $post->post_title, 'value' => $post->post_title );
}
Next, we’re going to loop through the posts we retrieved using the get_posts() function and create an option array for each post. For the “text” property we will use the Post Title and for the “value” property we will use the same. In some cases you may want to collect the ID of the selected post. If so you’d use $post->ID instead of $post->post_title; however, for our goal of recording the users favorite post, the post title is sufficient.
$field->choices = $choices;
Once we’ve looped through all of the posts and created all of our options, we assign the $choices array (which has all of our new options) to the $field choices property.
Add a Placeholder Choice
$field->placeholder = 'Select a Post';
We also want to make the first option in the drop down a “placeholder” choice. It let’s the user know what they are supposed to do with this drop down (ie “Select a Post”). We do this by assigning the choice text to the fields placeholder property.
When the drop down is rendered on the form the placeholder choice will have an empty value for the “value” property. This ensures that if this is a required field, that the user must select an option other than the placeholder option. Failing to do so will generate a validation error.
What about Checkboxes?
Checkbox fields can also be dynamically populated, but they require additional handling since their structure is created by a fieldset of inputs and choices. See this example code for Dynamically Populating a Checkbox as included in our gform_pre_render documentation.
Conclusion
That’s all there is to it! When you view your form on the front end you should now see that your select field is populated with a list of all your current posts.