Posted on by

Creating Custom Form Elements

Sometimes it’s necessary to create a custom form element to handle a specific need for a UI element in a Participants Database form. The means for doing that have been set up in the plugin, you’ll  definitely need some coding skills to get this done, so this post will only briefly cover the basic steps to setting up a custom form element. You are expected to know how to make this into your own custom form element.

There are 3 steps to take to set up a custom form element:

  1. Register the element with Participants Database
  2. Define the HTML for showing the form element in a form
  3. Define how the element’s value is displayed when not in a form

Register Your Custom Element

The filter pdb-set_form_element_types is used to add the new form element identifier. The full definition array of form element types is passed through, a new element should be added to the array in the form: $type_handle => $title. Your custom form element type will show up in the Form Element dropdown on the Manage Database Fields page.

Showing a Custom Form Element in a Form

For this, we use the pdb-form_element_build_{$type} action.

This action is triggered when a form element is instantiated. When the element is instantiated, the PDb_FormElement object will be passed to the action handler. The handler is expected to fill the ‘output’ property with the HTML string. The handler argument is passed by reference so other changes to the element object are possible in addition to defining the output HTML.

This action can also be used to override an existing element build function. If the FormElement object already has it’s output property filled with HTML, the standard build method will be skipped. For instance, if you wanted to modify how the “link” element was displayed, you could use the “pdb-form_element_build_link” hook to define your new HTML for that element. The normal way of building that element would then be skipped.

Showing the Value of a Custom Form Element

Each form element has a way to show it’s value in a non-form context, and that can be customized as well. For that, we use the pdb-before_display_form_element filter which is supplied the raw value of the field and the PDb_Field_Item object for the element. Typically, you’d test the field object to see if it was your custom form element, then return the appropriate display HTML. Be sure your filter returns a boolean false for form elements you don’t want to alter!

An Example

Let’s say you want to create a custom form element that stores an array of 3 values. You’re giving the element a handle of ‘array’ and a title of ‘List.’ The “pdb-set_form_element_types” filter is used to add those terms to the list of elements available in the field definition page.

The filters and actions need to define the custom element would be added like this:

add_filter( 'pdb-set_form_element_types', 'my_array_register_element' );
add_action( 'pdb-form_element_build_array','my_array_element_building_function' );
add_filter( 'pdb-before_display_form_element','my_array_element_value_display_function', 10, 2 );

The my_array_register_element() function adds the field name to the list of elements. The my_array_element_building_function() sets the PDb_FormElement object ‘output’ property with the HTML needed to display the element in a form. The my_array_element_value_display_function() returns the display value of the form element.

Here is the full code for our example. This one is way too simple to be used as-is, it’s only to show you how the parts go together, you can take it from here.

18 thoughts on “Creating Custom Form Elements

  1. Hello, Roland.

    I’ve tried to use your example code to create a simple array of strings. So I just uploaded the file ‘as-is’. I’ve managed to add my values to the array, but the output was wrong (both at the front-end and back-end).

    After some debugging I’ve managed to track down the problem. It deals with data serialization.

    With the current version published above ‘$field->value’ will return:

    a:3:{i:0;s:3:”red”;i:1;s:4:”blue”;i:2;s:5:”green”;}

    So before doing anything with the data, we should pass it through the ‘unserialize()’ PHP function.

    Here’s my quick fix for that: https://pastebin.com/Vf23nyEf

    Now the code works as expected.

    1. Thanks for this, very helpful. The code was written some time ago, it needed to be updated.

  2. I read all this with great interest… but I just cant figure out how to apply it to my situation.

    I have a the following:

    Field 1 -> Radio buttons with 5 regions and N/A.

    Field 2 -> Dropdown menu with a long list of countries

    When the user selects Region 1, I would like Field 2 to show only those countries in Region 1 .

    Same for all 5

    When N/A is selected in Field 1, Field 2 should also say N/A

    Is this possible?

    1. Something dynamic like this requires custom javascript, it can’t be done with a custom form element because it has to respond instantly to the user’s actions. The custom form element is built on the server side, so it can’t respond to the user’s actions.

      The best way to do this is to use a Custom Template for your form, set up your fields so that they have all the information for all cases, then add your custom javascript to the template which performs the necessary changes to the elements based on the selected values.

      I have another tutorial that may be helpful to you: Dropdown Selectors: limit selections based on another selector

  3. First, thanks for this amazing plugin! I’ve been looking for a way to have third parties contribute to and search a database for a while, and I’m so glad I finally found your excellent plugin! I appreciate your documentation support as well.

    I have a question about customizing the display of a field…and it may or may not require creating a custom form element. I have a hidden variable that gets set via the page the form is submitted from so that I can specify multiple record types. I’d like to be able to display those record types on lists and as search variables (I have purchased the multisearch plugin). Is there a way to customize the display of those so that instead of the webpage slug I show a more human readable name? So, if the form_type = ‘foo-bar’, I want the display to be “Foo Bar”.

    Thoughts on how I could do this?

    1. OK, the best way to do this is to use part of what is explained in the Custom Form Element tutorial.

      You should use the ‘pdb-before_display_form_element’ filter and create a handler for that filter that will take the incoming value and use that to reference an array of display values, then return the display value. A simple example:

       'Foo Bar',
         );
      
        if ( $field->name() === 'my_field' && isset( $display_values[$value] ) ) {
          $value = $display_values[$value];
        }
        return $value;
      }
      ?>

      that assumes your field has a name of ‘my_field’

      1. Thanks, this is perfect! Where’s the best place to add this so it is preserved through updates? Should it be a standalone file in the custom_templates folder (I have your add-on) so that it survives updates?

        1. Responding to myself. I tried adding this directly to the functions.php file and also tried installing it as a functionality plugin. Neither seems to work, and tracing through all of the code…I can’t figure out why. I did run the plugin update today, but I don’t see any changes that would relate to this filter or the get_field_value_display function.

        2. OK, looks like I got it wrong. You can’t test $value because it will be empty, the function is supposed to return the value.

          The value is in the $field object.

          So, the modified code is this:

           'Foo Bar',
             );
          
            if ( $field->name() === 'my_field' && isset( $display_values[$field->value()] ) ) {
              $value = $display_values[$field->value()];
            }
            return $value;
          }
          ?>
        3. Thanks! Through some trial-and-error I had figured that out…but not the reasoning why. I’m learning a ton through your amazingly-documented plugin.

  4. Hi Roland,
    Thanks again for this great plugin. I’ve been baffling with adding a new custom form element to the plugin but its been quite tricky, till I landed on this page, though it still presents a challenge.
    I needed to create a form element called “List” by which a user can add an infinite number of rows of data each with about 3 columns, just by clicking a plus icon, or add new row button. Then I hoped to be able to collect this data in a list table. I hate to ask much, so I do this only after failing several times, any help is highly appreciated. Thank you so much,

    Regards,
    PHILIP.

    1. Hi Philip,

      I have something like this in development, and I can tell you it is a fairly complex and involved project. I’m probably trying to do more with it that you need, but even in simplified form it’s not something I can help you with in a support forum.

  5. […] script is based on the one presented in Creating Custom Form Elements and that article has a more detailed description of the filters and how they work. Briefly, there […]

  6. Hi, I am using your excellent plugin to help manage volunteers on my site. I’ve been following along this tutorial to create a custom form element that is made up of 3 text inputs, and 2 radio inputs, all grouped as an array under the field name. When the form is submitted, I am able to get the custom form element value stored in the database, but when viewing any participant submission records in the “Edit Existing Participant Record” page on the wp admin backend my custom form elements remain blank. Is there a way to get my custom form element values to show up in this form ? Thanks in advance

    1. Hi Andy,

      I understand the problem…I messed up! I did not provide a complete description of how to provide the HTML for the form element…I was missing the part of how to show the saved value. I have updated the post with that information. Take a look at the my_array_element_building_function function to see how those values are added.

      You may need to insert a debug statement into the function to see what format your value is coming in as so that you can place the values in the right location. I use a statement like this (you’ll need to have your PHP error log set up):

      error_log(__FUNCTION__.' value: ' . print_r($field->value,1) );

      1. Hi Roland,

        Confirming that the udpate worked perfectly. Thanks for the quick response and this great plugin !

  7. Hi, I’m using your Plugin for a huge database and I need to make a field with multiple dropdown list fixed to a maximum selection of 3 categories then this field have to be dependent of the following one which is another dropdown list fixed to a maximum selection of 5 other categories. I really don’t know hot to set it up…can you help me please?
    Then can I be able to to send emails to specific groups of these crossed categories from your plugin? If yes how?
    Thank you…a lot!

    1. You’ll need to know some javascript and have some PHP coding skills to set this up, and it’s not particularly easy. You can get a good start by using the Chosen Multiselect add-on, which can be customized to limit the number of options. More difficult is limiting the choices in one control based on the selection in another. This requires organizing the data so that your javascript can enable/disable blocks of selections based on the other selector’s value.

      Sending emails to groups is possible using the Email Expansion Kit add-on for Participants Database

Leave a Reply to Andy Cancel reply

Your email address will not be published. Required fields are marked *

Would you like to be notified of followup comments via e-mail? You can also subscribe without commenting.

18 thoughts on “Creating Custom Form Elements

  1. Hello, Roland.

    I’ve tried to use your example code to create a simple array of strings. So I just uploaded the file ‘as-is’. I’ve managed to add my values to the array, but the output was wrong (both at the front-end and back-end).

    After some debugging I’ve managed to track down the problem. It deals with data serialization.

    With the current version published above ‘$field->value’ will return:

    a:3:{i:0;s:3:”red”;i:1;s:4:”blue”;i:2;s:5:”green”;}

    So before doing anything with the data, we should pass it through the ‘unserialize()’ PHP function.

    Here’s my quick fix for that: https://pastebin.com/Vf23nyEf

    Now the code works as expected.

    1. Thanks for this, very helpful. The code was written some time ago, it needed to be updated.

  2. I read all this with great interest… but I just cant figure out how to apply it to my situation.

    I have a the following:

    Field 1 -> Radio buttons with 5 regions and N/A.

    Field 2 -> Dropdown menu with a long list of countries

    When the user selects Region 1, I would like Field 2 to show only those countries in Region 1 .

    Same for all 5

    When N/A is selected in Field 1, Field 2 should also say N/A

    Is this possible?

    1. Something dynamic like this requires custom javascript, it can’t be done with a custom form element because it has to respond instantly to the user’s actions. The custom form element is built on the server side, so it can’t respond to the user’s actions.

      The best way to do this is to use a Custom Template for your form, set up your fields so that they have all the information for all cases, then add your custom javascript to the template which performs the necessary changes to the elements based on the selected values.

      I have another tutorial that may be helpful to you: Dropdown Selectors: limit selections based on another selector

  3. First, thanks for this amazing plugin! I’ve been looking for a way to have third parties contribute to and search a database for a while, and I’m so glad I finally found your excellent plugin! I appreciate your documentation support as well.

    I have a question about customizing the display of a field…and it may or may not require creating a custom form element. I have a hidden variable that gets set via the page the form is submitted from so that I can specify multiple record types. I’d like to be able to display those record types on lists and as search variables (I have purchased the multisearch plugin). Is there a way to customize the display of those so that instead of the webpage slug I show a more human readable name? So, if the form_type = ‘foo-bar’, I want the display to be “Foo Bar”.

    Thoughts on how I could do this?

    1. OK, the best way to do this is to use part of what is explained in the Custom Form Element tutorial.

      You should use the ‘pdb-before_display_form_element’ filter and create a handler for that filter that will take the incoming value and use that to reference an array of display values, then return the display value. A simple example:

       'Foo Bar',
         );
      
        if ( $field->name() === 'my_field' && isset( $display_values[$value] ) ) {
          $value = $display_values[$value];
        }
        return $value;
      }
      ?>

      that assumes your field has a name of ‘my_field’

      1. Thanks, this is perfect! Where’s the best place to add this so it is preserved through updates? Should it be a standalone file in the custom_templates folder (I have your add-on) so that it survives updates?

        1. Responding to myself. I tried adding this directly to the functions.php file and also tried installing it as a functionality plugin. Neither seems to work, and tracing through all of the code…I can’t figure out why. I did run the plugin update today, but I don’t see any changes that would relate to this filter or the get_field_value_display function.

        2. OK, looks like I got it wrong. You can’t test $value because it will be empty, the function is supposed to return the value.

          The value is in the $field object.

          So, the modified code is this:

           'Foo Bar',
             );
          
            if ( $field->name() === 'my_field' && isset( $display_values[$field->value()] ) ) {
              $value = $display_values[$field->value()];
            }
            return $value;
          }
          ?>
        3. Thanks! Through some trial-and-error I had figured that out…but not the reasoning why. I’m learning a ton through your amazingly-documented plugin.

  4. Hi Roland,
    Thanks again for this great plugin. I’ve been baffling with adding a new custom form element to the plugin but its been quite tricky, till I landed on this page, though it still presents a challenge.
    I needed to create a form element called “List” by which a user can add an infinite number of rows of data each with about 3 columns, just by clicking a plus icon, or add new row button. Then I hoped to be able to collect this data in a list table. I hate to ask much, so I do this only after failing several times, any help is highly appreciated. Thank you so much,

    Regards,
    PHILIP.

    1. Hi Philip,

      I have something like this in development, and I can tell you it is a fairly complex and involved project. I’m probably trying to do more with it that you need, but even in simplified form it’s not something I can help you with in a support forum.

  5. […] script is based on the one presented in Creating Custom Form Elements and that article has a more detailed description of the filters and how they work. Briefly, there […]

  6. Hi, I am using your excellent plugin to help manage volunteers on my site. I’ve been following along this tutorial to create a custom form element that is made up of 3 text inputs, and 2 radio inputs, all grouped as an array under the field name. When the form is submitted, I am able to get the custom form element value stored in the database, but when viewing any participant submission records in the “Edit Existing Participant Record” page on the wp admin backend my custom form elements remain blank. Is there a way to get my custom form element values to show up in this form ? Thanks in advance

    1. Hi Andy,

      I understand the problem…I messed up! I did not provide a complete description of how to provide the HTML for the form element…I was missing the part of how to show the saved value. I have updated the post with that information. Take a look at the my_array_element_building_function function to see how those values are added.

      You may need to insert a debug statement into the function to see what format your value is coming in as so that you can place the values in the right location. I use a statement like this (you’ll need to have your PHP error log set up):

      error_log(__FUNCTION__.' value: ' . print_r($field->value,1) );

      1. Hi Roland,

        Confirming that the udpate worked perfectly. Thanks for the quick response and this great plugin !

  7. Hi, I’m using your Plugin for a huge database and I need to make a field with multiple dropdown list fixed to a maximum selection of 3 categories then this field have to be dependent of the following one which is another dropdown list fixed to a maximum selection of 5 other categories. I really don’t know hot to set it up…can you help me please?
    Then can I be able to to send emails to specific groups of these crossed categories from your plugin? If yes how?
    Thank you…a lot!

    1. You’ll need to know some javascript and have some PHP coding skills to set this up, and it’s not particularly easy. You can get a good start by using the Chosen Multiselect add-on, which can be customized to limit the number of options. More difficult is limiting the choices in one control based on the selection in another. This requires organizing the data so that your javascript can enable/disable blocks of selections based on the other selector’s value.

      Sending emails to groups is possible using the Email Expansion Kit add-on for Participants Database

Leave a Reply to Andy Cancel reply

Your email address will not be published. Required fields are marked *

Would you like to be notified of followup comments via e-mail? You can also subscribe without commenting.