Tuesday, November 22, 2011

[WordPress Contact Form 7] Populate Select Dropdown from Database

Contact Form 7 (CF7) is a popular plugin for the WordPress CMS. It supports a few basic form components that allows user building a form quickly. One particular problem I had is to populate a drop down selection box from content stored in the database (e.g., a list of vacant positions). To dynamically populate dropdown options is not an uncommon task for site builders. And if you know something about programming, this wouldn't be hard either.

With CF7, you can only fill your options by hand. I have looked around for solutions, and found this post on the forum. However, it only appears to be working but not quite -- every time it rebuilds the options from database regardless user input, and nothing will be sent on submission (see the last comment in this post).

I then had to worked out my way; I believe this is original, so copy right reserved *_^. Here is how. (By the way, the version I am using is Contact Form 7 3.0.1).

In the wp-content\plugins\contact-form-7\modules\ folder, find the select.php. This is the file to be modified. (In general, I do NOT like to hack into the plugin source code. This will make upgrade difficult.)

1.
In function wpcf7_select_shortcode_handler, $values, $labels and $defaults need to be redefined for your customised dropdown. They are arrays for dropdown values, dropdown texts and default selection respectively. I have the following snippet right after $options are parsed (after line 50). Here my select field ID is "position".

if ($name == 'position') {
  // query the positions
  $positions = new WP_Query('YOUR_QUERY');
  
  while( $positions->have_posts() ) : $positions->the_post();
    array_push( $values, get_the_ID() );     // post ID as option value
    array_push( $labels, get_the_title() );  // post title as option text
  endwhile;
  
  // set the key of the default selection
  array_push( $defaults, 1 + array_search($YOUR_DEFAULT_VALUE, $values) );
} 

2.
In function wpcf7_select_validation_filter, you need to re-fill the dropdown option values before the post operation because they cannot be found in the shortcode. They will be needed in $_POST later. I have the following snippet right after the local variable definitions. The code is very similar.

if ($name == 'position') {
  // query the positions
  $positions = new WP_Query('YOUR_QUERY');
  while( $positions->have_posts() ) : $positions->the_post(); 
    array_push( $values, get_the_ID() );
  endwhile;
} 

And that is it.

6 comments:

  1. Great one, thanx! One question though. This would return the post_ID in the mail I receive, but I would prefer the post_title. I just can't seem to figure this out, if I change get_the_ID to get_the_title, it remains blank. Any advice?
    Thanx!

    ReplyDelete
  2. Hi Travis, thanks for the question. The way CF7 works is that only the dropdown values are submitted, dropdown texts are not. Without too much ado, you may let the dropdown values to be concatenation of ID and title, ie., having

    array_push( $values, get_the_ID() . ' ' . get_the_title() );

    instead of array_push( $values, get_the_ID() );

    Of course, then you need to modify the $YOUR_DEFAULT_VALUE selection.

    Hope that helps.
    Merry Christmas and Happy New Year!

    ReplyDelete
  3. Hi Joseph, thanks a lot for answering my question. It works!
    I don't really get why I can't just use my post titles as the value so I wouldn't need the ID. For 'normal' CF7 droplists the formvalues can be text, so why not is this case? I don't really need the ID, just the title, butttt...
    it's not a big issue and I'm glad I do have the title now, so it does help!
    Thanx for the effort and a Happy New Year to you too!

    ReplyDelete
  4. Hi Travis,

    Of course, you can forget about the IDs and just use the titles as your dropdown values as well as texts. The only draw back is that searching for $YOUR_DEFAULT_VALUE is much easier with ID than with title (in my case, I want to get a default selection when the page is loaded. Probably you don't need to do that).

    ReplyDelete
  5. hi, i would want that my text area will auto fill from selected dropdown. Will this work too?

    ReplyDelete