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
- Test if widget exists
- If it does…
- Start capturing output
- Output widget
- End capturing output
- Return captured output
- If it doesn’t exist…
- 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
-
Great post!, thanks! :)
-
Chris, this is awesome. Thanks!
I’ve wondered how difficult it would be to wedge a widget into a content page. :D -
Thanks for sharing Chris! Just what I was looking for.
By the way, slight typo on 2.4. above. -
What if you need to call the same widget more than once? How do you handle the name collisions?
-
Hey Chris
Can you call this via php at all?
Maybe something like this?
<?php widget(widget_name=Your_Custom_Widget') ; ?></code>
-
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("&", '&' ,$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"]
-
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.
-
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
-
The first occurrence of
$class
(insprintf()
) is undefined. And where do you get the$instance
from?Why did you give the function
widget()
such a generic name? -
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
-
am i doing something wrong? i tried to insert the code into functions.php and it broke my entire installation
-
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.