Like the blog? Get the book »

Call a Widget with a Shortcode

Call a Widget with a Shortcode

We covered how to run a shortcode in a widget. But what about inserting a widget with a shortcode? I recently had this situation come up.

I had a single page where I just wanted to be able to chuck in a widget without the whole rigmarole of creating a special widgetized area and probably a custom page template for that widgetized area and so forth and so on.

I wanted to just put [widget widget_name="my_widget"] in the pages content and have that widget pop in. Turns out it wasn’t as easy I wanted it to be, but it’s not that bad…

The answer was creating a custom function for the functions.php file which would output any widget by name. There is a function just for that: the_widget() (incomplete codex page).

The logic

  1. Test if widget exists
  2. If it does…
    1. Start capturing output
    2. Output widget
    3. End capturing output
    4. Return captured output
  3. If it doesn’t exist…
    1. Output fail message

The code for functions.php

function widget($atts) {
    
    global $wp_widget_factory;
    
    extract(shortcode_atts(array(
        'widget_name' => FALSE
    ), $atts));
    
    $widget_name = wp_specialchars($widget_name);
    
    if (!is_a($wp_widget_factory->widgets[$widget_name], 'WP_Widget')):
        $wp_class = 'WP_Widget_'.ucwords(strtolower($class));
        
        if (!is_a($wp_widget_factory->widgets[$wp_class], 'WP_Widget')):
            return '<p>'.sprintf(__("%s: Widget class not found. Make sure this widget exists and the class name is correct"),'<strong>'.$class.'</strong>').'</p>';
        else:
            $class = $wp_class;
        endif;
    endif;
    
    ob_start();
    the_widget($widget_name, $instance, array('widget_id'=>'arbitrary-instance-'.$id,
        'before_widget' => '',
        'after_widget' => '',
        'before_title' => '',
        'after_title' => ''
    ));
    $output = ob_get_contents();
    ob_end_clean();
    return $output;
    
}
add_shortcode('widget','widget'); 

Usage

Now in Post/Page content, you can use the widget by referencing it by name:

[widget widget_name="Your_Custom_Widget"]

16 responses

  1. Great post!, thanks! :)

  2. Chris, this is awesome. Thanks!
    I’ve wondered how difficult it would be to wedge a widget into a content page. :D

  3. Thanks for sharing Chris! Just what I was looking for.
    By the way, slight typo on 2.4. above.

  4. Danny G Smith

    What if you need to call the same widget more than once? How do you handle the name collisions?

  5. Hey Chris

    Can you call this via php at all?

    Maybe something like this?

    <?php widget(widget_name=Your_Custom_Widget') ; ?></code>

  6. Check out the function in the code above:

    the_widget

  7. Michael Krapf

    Is there a way to include an $instance in the shortcode?

    An example of the full version would be:

    <?php the_widget('WP_Widget_Text', $instance, $args); ?>

    If so, then you could narrow the call using instance:

    • title
    • text
    • filter

    So in addition to calling the widget, I would like to specify which version of the widget.

    • Patrik Spathon

      Is it something like this you were looking for?

      extract(shortcode_atts(array(
      	'widget_name' => FALSE,
      	'instance'    => ''
      ), $atts));
      
      $instance = str_ireplace("&", '&' ,$instance);

      then you can set the instances for the widget. Usage:

      [widget widget_name="WP_Widget_Pages" instance="title=Pages&sortby=menu_order&exclude=2,41"]

  8. Todd Halfpenny

    This is very handy and something I may need to turn into a plugin so that folk don’t need to dabble with the code.

    Might be worth doing a spot of self promotion too (sorry ;-) ) for a plugin I have written that let’s you include a whole widgetised area inline insde wordpress page/post content… if you’re interested check out the Widgets on Pages plugin over at wordpress.org.

    I’d be interested in hearing your views on this.

  9. This is great, thanks. I’d like to second Michael’s question. I don’t understand how to call a particular text widget. Is there any way to specify ID or similar? many thanks

    • I wish I had a perfect answer… The data exists so there is SOME way to do it. With this code though we are basically creating a new instance of the widget when it is called, not calling a pre-existing widget as defined in the Widgets area of the admin.

  10. Thomas Scholz

    The first occurrence of $class (in sprintf()) is undefined. And where do you get the $instance from?

    Why did you give the function widget() such a generic name?

  11. Chris Schryer

    I might be well out to sea here, but I thought you could only call shortcodes on WordPress.com blogs, not self-hosted ones? I tried, just in case, and all that happens is I get the shortcode outputted as text. Any ideas? Am I missing something obvious? Thanks

  12. am i doing something wrong? i tried to insert the code into functions.php and it broke my entire installation

  13. I have released a plugin, Widget Instance ,that addresses the question that Michael Krapf and Neil asked in the comment thread and that Chris Coyier left unanswered as far as providing an implementation.

Comments are closed for this post. Contact us with any critical information.
© 2009–2024 Digging Into WordPress Powered by WordPress Monzilla Media shapeSpace