Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have attempted to develop a way to set something in a widget only if the widget exists in a specific sidebar. The code below looks for sidebar called 'footer' and shows the select option above the default options in the widget.

However, it doesn't appear when I drag a new widget into the sidebar. When I press save, the option then appears where I will have to then select the option and hit save again. What am I missing to ensure it loads as soon as it's dragged into the sidebar?

function mytheme_colspan_widget_extend( $instance, $widget ) {
    if ( !isset($instance['colspan']) )
    $instance['colspan'] = 3; // set a default if none is set
    foreach ( wp_get_sidebars_widgets() as $sidebar => $widgets ) {
       if ('footer' == $sidebar && in_array( $widget->id, $widgets )) {
        echo "<p>\n";
        echo "\t<label for='widget-{$widget->id_base}-{$widget->number}-colspan'>Column Span:</label> \n";
        ?>
        <select name="widget-<?php echo $widget->id_base.'['.$widget->number.'][colspan]'; ?>" id="widget-<?php echo $widget->id_base.'-'.$widget->number; ?>-colspan">
        <option>Select:</option>
        <option<?php if ($instance['colspan']=='1') {echo ' selected';} ?> value="1">1</option>
        <option<?php if ($instance['colspan']=='2') {echo ' selected';} ?> value="2">2</option>
        <option<?php if ($instance['colspan']=='3') {echo ' selected';} ?> value="3">3</option>
        <option<?php if ($instance['colspan']=='4') {echo ' selected';} ?> value="4">4</option>
        <option<?php if ($instance['colspan']=='5') {echo ' selected';} ?> value="5">5</option>
        <option<?php if ($instance['colspan']=='6') {echo ' selected';} ?> value="6">6</option>
        <option<?php if ($instance['colspan']=='7') {echo ' selected';} ?> value="7">7</option>
        <option<?php if ($instance['colspan']=='8') {echo ' selected';} ?> value="8">8</option>
        <option<?php if ($instance['colspan']=='9') {echo ' selected';} ?> value="9">9</option>
        <option<?php if ($instance['colspan']=='10') {echo ' selected';} ?> value="10">10</option>
        <option<?php if ($instance['colspan']=='11') {echo ' selected';} ?> value="11">11</option>
        <option<?php if ($instance['colspan']=='12') {echo ' selected';} ?> value="12">12</option>
        </select>
        <?php
        echo "</p>\n";
       }
    }
    return $instance;
}
add_filter('widget_form_callback', 'mytheme_colspan_widget_extend', 10, 2);


function mytheme_colspan_widget_update( $instance, $new_instance ) {
    $instance['colspan'] = $new_instance['colspan'];
    return $instance;
}
add_filter( 'widget_update_callback', 'mytheme_colspan_widget_update', 10, 2 );
share|improve this question
add comment

1 Answer

You need to get the array of sidebars and their widgets with wp_get_sidebars_widgets(), then check if the current widget is in the 'footer' sidebar:

$sidebars = wp_get_sidebars_widgets();

 if ( in_array( $widget->id, $sidebars['footer'] ) ) {

      /* Display form fields here */
 }

Update:

There is one caveat to this, which you have discovered. The widget form is output before a new widget is assigned to a sidebar, and is not reloaded until the widget settings are saved. If you wish all of the settings to be immediately available, you will have to solve this with either CSS or JavaScript. I think CSS will be the best way to go, if your footer sidebar will always have the same numeric ID (this should be true if the number of sidebars isn't dynamic - though people could add extra custom sidebars, I suppose).

Basically, if the widget isn't hooked to any sidebar, you output your form input, and hide it using CSS unless it is moved to the correct sidebar.

You can perform the check like this:

if ( '__i__' == $widget->number ) { 

    /* This widget isn't hooked to a sidebar yet. */ 
}

So your complete check would look something like:

$sidebars = wp_get_sidebars_widgets();

if ( '__i__' == $widget->number || in_array( $widget->id, $sidebars['footer'] ) ) {

     /* Display form fields here */
}

Example of the CSS, assuming that the footer sidebar will always be number 3:

<style type="text/css">
.show-if-sidebar-3 {
       display: none;
}

#sidebar-3 .show-if-sidebar-3 {
      display: block;
}
</style>

You could add those styles to your admin stylesheet, for example, and then add the show-if-sidebar-3 class to the paragraph tag that you wrap the extra fields in like so: <p class="show-if-sidebar-3">

I can't really think of an alternative, unless you want try using JavaScript to detect when a widget of this particular type is added to that particular sidebar, and immediately reload the form. That's much more complex though.

share|improve this answer
    
This does not work. $this->id outputs an error. I edited to this: foreach ( wp_get_sidebars_widgets() as $sidebar => $widgets ) { if ($sidebar=='footer') { ... } In a template file this all works, but in the function it ignores the if statement completely –  manc Aug 26 '13 at 8:46
    
Sorry, I neglected to note that this was a custom function that was being passed a widget instance, and not the form callback function within the widget. I've updated my answer with $widget->id instead. –  J.D. Aug 26 '13 at 13:06
    
That did the trick, thanks! One thing I do want to add to this is to change the order so this all outputs at the bottom rather than the top. I can't find any documentation on widget_form_callback –  manc Aug 27 '13 at 17:32
    
When the docs fail, check the source. As you can see, widget_form_callback is called before the form is output. You'll want to use in_widget_form instead. The argument order is different, and it is an action rather than a filter, but other than that, it should work the same way. –  J.D. Aug 27 '13 at 21:39
    
Have you changed the argument order? The function should now take its arguments like so: function my_widget_form_extend( $widget, $return, $instance ). You should have been getting some helpful errors from this - don't tell me you're developing with WP_DEBUG set to false? –  J.D. Aug 28 '13 at 21:34
show 9 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.