DiggingIntoWordPress

by Chris Coyier & Jeff Starr

Call a Widget with a Shortcode

Posted by on

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 such. 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 just by referencing it by name:

[widget widget_name="Your_Custom_Widget"]

16 Responses

  1. _DorsVenabili April 12, 2010

    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 April 13, 2010

    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. 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.

    • Is it something like this you were looking for?

      extract(shortcode_atts(array(
             'widget_name' => FALSE,
             'instance' => ''
      ), $atts));
      $instance = str_ireplace("&amp;", '&' ,$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. 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. 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. 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
    C

  12. Kerri Lotus July 8, 2010

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

  13. Ben Cooling June 11, 2012

    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. Contact us with any critical information. Thank you!

Code is poetry