How to register custom field settings in Gravity Forms

Gravity Forms field configuration with custom field settings

We’re big fans of Gravity Forms here at Growella; it’s easy enough to use that our editorial team can build forms without developer intervention, yet powerful enough that we can process the data any way we need to.

One frustrating aspect of Gravity Forms, however, is adding our own custom field settings to Gravity Forms’ fields. There doesn’t seem to be an easy-to-follow resource for adding these things, so we decided to write one ourselves.

If you’ve ever wanted to add your own custom field settings to Gravity Forms, read on!

Rendering the input

The first step to adding our own custom field settings is to render the actual markup for our setting. To do so, we’ll need to register a callback on one of three hooks: gform_field_standard_settings, gform_field_appearance_settings, or gform_field_advanced_settings, which correspond to the “General”, “Appearance”, and “Advanced” tabs (respectively) when configuring a Gravity Forms field.

All three hooks will receive the same arguments: the $position (Gravity Forms has a nicely-documented list of available positions) and the $form_id.

An example callback might look something like this:

/**
 * Render the autocomplete attribute setting.
 *
 * @param int $position The current property position.
 */
function render_my_setting( $position ) {

  // Replace 150 with whatever position you want.
  if ( 150 !== $position ) {
    return;
  }
?>

  <li class="my_attr_setting field_setting">
    <ul>
      <li>
        <label for="field_my_attr" class="section_label">
          <?php esc_html_e( 'My Attribute', 'text-domain' ); ?>
          <?php gform_tooltip( 'form_field_my_attr' ); ?>
        </label>
        <input id="field_my_attr" type="text" onchange="SetFieldProperty('myAttr', this.value)" />
      </li>
    </ul>
  </li>

<?php
}
add_action( 'gform_field_advanced_settings', 'render_my_setting' );

It’s a pretty simple function, but there are a few key things to highlight:

  • We’re checking the $position and making sure we only render the input when we’re in the right spot; the hooks get called dozens of times while a field’s settings are being assembled, so it’s important that we only render it where we mean to.
  • We’re calling gform_tooltip() to render our tooltip; we’ll cover this more in-depth below.
  • The <input /> element has an onchange attribute that calls Gravity Forms’ SetFieldProperty() function. This is what will actually save the value.

Whitelisting your custom field setting

Now that we’ve created an interface for our custom field setting, we need to tell Gravity Forms to both recognize and populate it; to do this, we’ll use a little bit of JavaScript on the gform_editor_js action.

/**
 * Custom scripting for our custom field setting.
 */
function custom_field_setting_js() {
?>

  <script type="text/javascript">

    /*
     * Tell Gravity Forms that every field type should
     * support the .my_attr_setting input.
     */
    jQuery.map(fieldSettings, function (el, i) {
      fieldSettings[i] += ', .my_attr_setting';
    });

    /*
     * When the field settings are initialized, populate
     * the custom field setting.
     */
    jQuery(document).on('gform_load_field_settings', function(ev, field) {
      jQuery('#field_my_attr').val(field.myAttr || '');
    });
  </script>

<?php
}
add_action( 'gform_editor_js', 'custom_field_setting_js' );

This bit of JavaScript does two things:

  1. Tells Gravity Forms that all field types (“Single Line Text”, “Number”, etc.) should show the .my_attr_setting list item that we rendered in render_my_setting(); if you wanted to only apply the input to a subset of fields, you could filter that here.
  2. When a field’s settings are expanded, populate the input with the value stored in the field’s myAttr property. This key matches the property key we set in the SetFieldProperty() event callback earlier.

Registering tooltips for custom field settings

At this point, we should have everything we need to render and save custom field settings for Gravity Forms’ fields, but we’re not quite done yet! One of the draws to Gravity Forms is how simple it makes form editing in WordPress, so let’s continue that tradition and add a tooltip to our new, custom field setting.

The code we used earlier to render the field setting earlier already includes a call to gform_tooltip() with the argument of “form_field_my_attr”, so all we need to do is tell Gravity Forms what the content of that tooltip should be.

Register a new function, attaching it to the gform_tooltips filter:

/**
 * Populate the "My Attribute" tooltip.
 *
 * @param array $tooltips Existing Gravity Forms tooltips.
 * @return array The $tooltips array with a new key for
 * form_field_my_attr.
 */
function my_attr_tooltip( $tooltips ) {
  $tooltips['form_field_my_attr'] = sprintf(
    '<h6>%s</h6>%s',
    __( 'My Attribute', 'text-domain' ),
    __( 'This text should be helpful!', 'text-domain' )
 );

 return $tooltips;
}
add_filter( 'gform_tooltips', 'my_attr_tooltip' );

Bonus: rendering custom attributes on Gravity Forms fields

This may not be necessary in all cases, but sometimes you need to be able to inject custom attributes into the front-end inputs generated by Gravity Forms.

Due in part to the way that Gravity Forms is built, there isn’t an easy way to say “inject this attribute with this name and that value” via a filter, but we’re able to do so using regular expressions and the gform_field_content filter:

/**
 * Inject my-attr attributes into individual form fields.
 *
 * @param string $markup The markup for an individual field.
 * @param GF_Field $field The Gravity Forms Field object.
 */
function inject_my_attr_attribute( $markup, $field ) {
  if ( ! isset( $field->myAttr ) || ! $field->myAttr ) {
    return $markup;
  }

  // Find the first input, select, or textarea element.
  $regex = '/\<(?:input|select|textarea)\s+[^\>]+?(\s*\/?\>){1}/im';

  if ( ! preg_match( $regex, $markup, $input ) ) {
    return $markup;
  }

  $my_attr = sprintf( ' my-attr="%s"', esc_attr( $field->myAttr ) );
  $element = str_replace( $input[1], $my_attr . $input[1], $input[0] );

  return str_replace( $input[0], $element, $markup );
}
add_filter( 'gform_field_content', 'inject_my_attr_attribute', 10, 2 );

Note: Regular expressions can be a tough concept to grasp, and the pattern used above is only effective on the first input it finds for each field; if you’re rendering more advanced fields like “Address” or “Name”, you may get unexpected results!

This filter will attempt to inject a my-attr attribute into the input, select, or textarea element for any Gravity Forms field that has a value for your custom attribute. It’s only an example, of course, but it should give you a path forward if you can’t otherwise control the output of your fields.

A practical example: autocomplete fields

For a great example of where custom field settings can be useful, look no further than our Gravity Forms: Autocomplete Fields plugin, which is currently in-development.

This plugin will automatically inject HTML5 autocomplete attributes into Gravity Forms inputs, helping browsers understand what kinds of content each field contains. We hope it’ll help our users have a better experience on Growella, and it’s something we plan on releasing via WordPress.org when it’s ready.

Leave a Reply