Lee Willis

Adding a dynamic select list to Contact Form 7

| 12 Comments

Contact Form 7 is a great, plugin that allows you to easily add contact forms to your WordPress site. Today, I wanted to make a small tweak to one of my contact forms so I could capture some better information.

Specifically, I often receive blog enquiries from people asking questions like “Can this plugin do XXX?” without any context. Since I have around 13 free plugins on WordPress.org, and around 14 sold through my own premium plugin site, and numerous others through other websites – it’s not always obvious which plugin people are asking about.

So – I did the obvious thing, and added a drop-down list and asked people to confirm which plugin they were contacting me about. The challenge was that rather than just hardcoding in the list of options, I wanted it to be dynamic, and generated in realtime.

I can see this being useful in lots of different situations so here’s my solution:

function ses_add_plugin_list_to_contact_form ( $tag, $unused ) {

    if ( $tag['name'] != 'plugin-list' )
        return $tag;

    $args = array ( 'post_type' => 'wpsc-product',
                    'numberposts' => 50,
                    'orderby' => 'title',
                    'order' => 'ASC' );
    $plugins = get_posts($args);

    if ( ! $plugins )
        return $tag;

    foreach ( $plugins as $plugin ) {
        $tag['raw_values'][] = $plugin->post_title;
        $tag['values'][] = $plugin->post_title;
        $tag['labels'][] = $plugin->post_title;
        $tag['pipes']->pipes[] = array ( 'before' => $plugin->post_title, 'after' => $plugin->post_title);
    }

    return $tag;
}
add_filter( 'wpcf7_form_tag', 'ses_add_plugin_list_to_contact_form', 10, 2);

That example picks up a select list called “plugin-list”, and adds to the options for every post retrieved by the call to get_posts. Here’s the setup of the default contact form:

You can see we’ve set the field name to “plugin-list” – so that our code above can make the changes to the right field, and we’ve provided a couple of fixed options – our dynamic ones will be added on after these.

Hopefully this comes in useful!

12 Comments

  1. Very nice! Just what I needed.

    I changed the code a little bit to make it a litte more general:

    $options = (array) $tag[‘options’];

    foreach ( $options as $option ) {
    if ( preg_match( ‘%^posttype:([-0-9a-zA-Z_]+)$%’, $option, $matches ) ) {
    $post_type = $matches[1];
    }
    }

    //check if post_type is set
    if(!isset($post_type)) {
    return $tag;
    }

    $args= array(
    ‘post_type’ => $post_type,
    ‘order’ => ‘ASC’,
    ‘orderby’ => ‘title’
    );
    $plugins = get_posts($args);

    This is how I use it:

    [select* your-shop posttype:shop]

    and it will collect al ‘shop’ posts.

    • Hi, is great. Could you please post the whole snippet, including the function name, parameters (if any) and the function call at the end? I´m trying to use your code but my php skills are limited. Thanks a lot!

  2. Really great! It’s working fine for me…

    But now i’m trying to show an ACF plugin custom field in front of the text of each select option.

    I’m trying it without success. Does someone know how to do it?
    tks =)

  3. This looks great! I am trying to change the code to show all custom fields: I have several custom fields with the same key (date) and different values. In the contact form I want visitors to be able to select any of the dates from all pages…

    Any ideas how? Thx! :-)

  4. is it possible to have a contact form 7 that changes with the selection made.
    ex: phone repairs, laptop repairs, gaming console repair.
    and when a person chooses one of the above the form changes for that selection.
    i hope you get the idea of what i trying to do.

    • It’s not really the topic of this article. There are a few solutions that a quick Google search turned up focussed on using javascript to show/hide the fields. If that’s not suitable I believe Gravity Forms offers conditional fields.

  5. This was working great, but suddenly this broke.

    I’m getting a fatal error on your line 19…
    Fatal error: Cannot access private property WPCF7_Pipes::$pipes….

    Could a CF7 update have broken this, or something else?

    • Yep – something changed in recent versions of CF7. You can just drop the line that refers to pipes and everything should work fine.

      So – just remove this line:

      $tag['pipes']->pipes[] = array ( 'before' => $plugin->post_title, 'after' => $plugin->post_title);

  6. hi, i’m add code and it working filed select, but when i’m submit => go to 404 page. i’m received email have all filed. how to check error?

    function cf7_catpost ( $tag, $unused ) {
    if ( $tag[‘name’] != ‘plugin-list’ )
    return $tag;

    $args = array ( ‘category’ => 4, ‘post_type’ => ‘post’,
    ‘numberposts’ => 6 );
    $plugins = get_posts($args);

    if ( ! $plugins )
    return $tag;

    foreach ( $plugins as $plugin ) {
    $tag[‘raw_values’][] = $plugin->post_title;
    $tag[‘values’][] = $plugin->post_title;
    $tag[‘labels’][] = $plugin->post_title;
    }

    return $tag;
    }
    add_filter( ‘wpcf7_form_tag’, ‘cf7_catpost’, 10, 2);

  7. I was attempting to get pipes working in a set of options built in the filter. I started off here, but found the same issue about [code]$tag[‘pipes’]->pipes[] = array ( ‘before’ => $plugin->post_title, ‘after’ => $plugin->post_title);[/code] not being valid any longer.

    Should you or anyone run into this same requirement and get stuck. I put together a couple sentences with examples: http://www.mattross.io/2014/08/25/programmatic-selectable-recipients-with-pipes-in-wpcf7/

    Thanks for the jump start!

Leave a Reply

Required fields are marked *.