dynamically add scripts to WP_Widget widget() method

I have a wordpress widget that has the standard outline like:

class my_widget extends WP_Widget{

function my_widget(){
   //do setup stuff
}

function form(){
   //do form stuff
}

function update(){
   //do update stuff
}

function widget($args, $instance){
   //how can we dynamically add style and script here

   //this does not work
   if($instance['val'] == 'test'){
      wp_register_script('test', plugins_url('test.js');
      wp_print_scripts('test');
   }else{
      wp_register_script('diff', plugins_url('diff.js');
      wp_print_scripts('diff');
   }
}

}

Read More

I am wondering if it’s possible to somehow add scripts dynamically to a wordpress widget… I am guessing that this would have to take place within the widget() method b/c that is the only place where dynamic variables are passed, but the problem is this function appears to be fired after scripts are added.

thanks for your thoughts

Related posts

Leave a Reply

4 comments

  1. I’m plucking this code out of my Total Widget Control plugin, so it might throw an error or two. I dunno, just let me know if it does. This is basically the widget code that I use for everything that I build.

        if (!function_exists("register_multiwidget")):
    
    /**
     * Register a widget
     * 
     * @param $widget
     */
    function register_multiwidget( $widget = null )
    {
        static $widgets;
        if (!isset($widgets))
        {
            $widgets = array();
        }
    
        if (is_null($widget)) return $widgets;
        if (!is_array($widget)) return false;
    
        $defaults = array(
            'id' => '1',
            'title' => 'Generic Widget',
            'classname' => '',
            'description' => '',
            'width' => 200,
            'height' => 200,
            'fields' => array(),
        );
    
        $widgets[$widget['id']] = wp_parse_args($widget, $defaults);
    
        return true;
    }
    
    /**
     * Get the registered widgets
     * 
     * @return array
     */
    function get_registered_widgets()
    {
        return register_multiwidget();
    }
    
    /**
     * Initialize the widgets
     * 
     * @return boolean
     */
    function init_registered_widgets()
    {
        //initialziing variables
        global $wp_widget_factory;
        $widgets = get_registered_widgets();
    
        //reasons to fail
        if (empty($widgets) || !is_array($widgets)) return false;
    
        foreach ($widgets as $id => $widget)
        {
            $wp_widget_factory->widgets[$id] =& new Multiple_Widget_Master( $widget );
        }
    
        return false;
    }
    
    /**
     * Multiple Widget Master Class
     * 
     * This class allows us to easily create qidgets without having to deal with the
     * mass of php code.
     * 
     * @author byrd
     * @since 1.3
     */
    class Multiple_Widget_Master extends WP_Widget
    {
    
    /**
     * Constructor.
     * 
     * @param $widget
     */
    function Multiple_Widget_Master( $widget )
    {
        $this->widget = apply_filters('twc_widget_setup', $widget);
        $widget_ops = array(
            'classname' => $this->widget['classname'], 
            'description' => $this->widget['description'] 
        );
        $this->WP_Widget($this->widget['id'], $this->widget['title'], $widget_ops);
    }
    
    /**
     * Display the Widget View
     * 
     * @example extract the args within the view template
     extract($args[1]); 
    
     * @param $args
     * @param $instance
     */
    function widget($args, $instance)
    {
        //initializing variables
        $widget = $this->widget;
        $widget['number'] = $this->number;
    
        $args = array(
            'sidebar' => $args,
            'widget' => $widget,
            'params' => $instance,
        );
    
        $show_view = apply_filters('twc_widget_view', $this->widget['show_view'], $widget, $instance, $args);
                ob_start();
                require_once $show_view;
    }
    
    /**
     * Update from within the admin
     * 
     * @param $new_instance
     * @param $old_instance
     */
    function update($new_instance, $old_instance)
    {
        //initializing variables
        $new_instance = array_map('strip_tags', $new_instance);
        $instance = wp_parse_args($new_instance, $old_instance);
    
        return $instance;
    }
    
    /**
     * Display the options form
     * 
     * @param $instance
     */
    function form($instance)
    {
        //reasons to fail
        if (empty($this->widget['fields'])) return false;
        do_action('twc_widget_before');
    
        $defaults = array(
            'id' => '',
            'name' => '',
            'desc' => '',
            'type' => '',
            'options' => '',
            'std' => '',
        );
    
        foreach ($this->widget['fields'] as $field)
        {
            $field = wp_parse_args($field, $defaults);
    
    
            if (isset($field['id']) && array_key_exists($field['id'], $instance))
                $meta = attribute_escape($instance[$field['id']]);
    
            if ($field['type'] != 'custom' && $field['type'] != 'metabox') 
            {
                echo '<p><label for="',$this->get_field_id($field['id']),'">';
            }
            if (isset($field['name']) && $field['name']) echo $field['name'],':';
    
            switch ($field['type'])
            {
                case 'text':
                    echo '<input type="text" name="', $this->get_field_name($field['id']), '" id="', $this->get_field_id($field['id']), '" value="', $meta ? $meta : $field['std'], '" class="twc_text" />', 
                    '<br/><span class="description">', $field['desc'], '</span>';
                    break;
                case 'textarea':
                    echo '<textarea class="twc_textarea" name="', $this->get_field_name($field['id']), '" id="', $this->get_field_id($field['id']), '" cols="60" rows="4" style="width:97%">', $meta ? $meta : $field['std'], '</textarea>', 
                    '<br/><span class="description">', $field['desc'], '</span>';
                    break;
                case 'select':
                    echo '<select class="twc_select" name="', $this->get_field_name($field['id']), '" id="', $this->get_field_id($field['id']), '">';
                    foreach ($field['options'] as $option)
                    {
                        echo '<option', $meta == $option ? ' selected="selected"' : '', '>', $option, '</option>';
                    }
                    echo '</select>', 
                    '<br/><span class="description">', $field['desc'], '</span>';
                    break;
                case 'radio':
                    foreach ($field['options'] as $option)
                    {
                        echo '<input class="twc_radio" type="radio" name="', $this->get_field_name($field['id']), '" value="', $option['value'], '"', $meta == $option['value'] ? ' checked="checked"' : '', ' />', 
                        $option['name'];
                    }
                    echo '<br/><span class="description">', $field['desc'], '</span>';
                    break;
                case 'checkbox':
                    echo '<input type="hidden" name="', $this->get_field_name($field['id']), '" id="', $this->get_field_id($field['id']), '" /> ', 
                         '<input class="twc_checkbox" type="checkbox" name="', $this->get_field_name($field['id']), '" id="', $this->get_field_id($field['id']), '"', $meta ? ' checked="checked"' : '', ' /> ', 
                    '<br/><span class="description">', $field['desc'], '</span>';
                    break;
                case 'custom':
                    echo $field['std'];
                    break;
                case 'metabox':
                    if ((isset($_REQUEST['action']) && $_REQUEST['action'] == 'edit')
                    || (isset($_REQUEST['action']) && $_REQUEST['action'] == 'add' && isset($_REQUEST['addnew'])))
                    echo '</div>
                    </div>
                    <div id="query_view_params" class="postbox">
                        <div class="handlediv" title="Click to toggle"><br></div>
                        <h3 class="hndle">
                            <span>Query View Parameters</span>
                        </h3>
                        <div class="inside">';
                    break;
            }
    
            if ($field['type'] != 'custom' && $field['type'] != 'metabox') 
            {
                echo '</label></p>';
            }
        }
        do_action('twc_widget_after');
        return;
    }
    
    }// ends Master Widget Class
    endif;
    

    Now, once you’ve pasted this into your functions.php file you can start declaring new widgets in seconds. Here’s the code to declare a new widget.

        register_multiwidget(array(
    'id' => 'first-custom-widget',  // Must be slug compatible, and unique, it's used a lot
    'title' => __('aaaFirst Widget'),   
    'description' => __('This is my description'),  
    'classname' => 'st-custom-wi',  
    'show_view' => 'path/to/my/widget_view_file.php',
    'fields' => array(
    array(
        'name' => 'Text box',
        'desc' => 'Enter something here',
        'id' => 'text',
        'type' => 'text',
        'std' => 'Default value 1'
    ),
    array(
        'type' => 'custom',
        'std' => '<hr/>'
    ),
    array(
        'name' => 'Textarea',
        'desc' => 'Enter big text here',
        'id' => 'textarea',
        'type' => 'textarea',
        'std' => 'Default value 2'
    
    ),
    array(
        'name' => 'Select box',
        'id' => 'select',
        'type' => 'select',
        'options' => array('Option 1', 'Option 2', 'Option 3')
    ),
    array(
        'name' => 'Radio',
        'id' => 'radio',
        'type' => 'radio',
        'options' => array(
        array('name' => 'Name 1', 'value' => 'Value 1'),
        array('name' => 'Name 2', 'value' => 'Value 2')
        )
    ),
    array(
        'name' => 'Checkbox',
        'id' => 'checkbox',
        'type' => 'checkbox'
    ),
    
    )
        ));
    

    Declare whatever fields that you want for your widget options with the array above and you’re almost done.

    The last thing that you need to do is paste your widgets html into your new file path/to/my/widget_view_file.php

    At the top of this widget view file add this following code: <?php extract($args[1]); ?> This will break out three variables for you to use:

    1. $sidebar
    2. $widget
    3. $params
  2. This widget enqueues all possible required scripts for the footer, but it also sets a hook on wp_print_footer_scripts that will deregister the scripts before they are printed, unless you change the array when printing the widget.

    class WPSE16208_Widget extends WP_Widget
    {
        // Key is script handle, value is boolean:
        // true if it should be printed, false otherwise
        protected $scripts = array();
    
        public function __construct()
        {
            parent::__construct( 'wpse16208', 'WPSE 16208 Widget' );
    
            wp_enqueue_script(
                'wpse16208_a',
                plugins_url( 'a.js', __FILE__ ),
                array(),
                false,
                true
            );
            $this->scripts['wpse16208_a'] = false;
            wp_enqueue_script(
                'wpse16208_b',
                plugins_url( 'b.js', __FILE__ ),
                array(),
                false,
                true
            );
            $this->scripts['wpse16208_b'] = false;
    
            add_action( 'wp_print_footer_scripts', array( &$this, 'remove_scripts' ) );
        }
    
        public function widget()
        {
            echo 'My widget';
    
            $this->scripts['wpse16208_a'] = true;
        }
    
        public function remove_scripts()
        {
            foreach ( $this->scripts as $script => $keep ) {
                if ( ! $keep ) {
                    // It seems dequeue is not "powerful" enough, you really need to deregister it
                    wp_deregister_script( $script );
                }
            }
        }
    }
    
  3. You could extend the WP_Widget class and add your init stuff to the constructor or overload the widget() method with your modified code. E.g.

    class WPSE_16208_Widget extends WP_Widget {
        function __construct( $id_base = false, $name, $widget_options = array(), $control_options = array() ) {
            parent::__construct($id_base, $name, $widget_options, $control_options);
    
            // do your stuff on init
        }
    
        function widget() {
            // overload WP_Widget::widget()
        }
    }