One way to do this would be to filter out all the other widgets in the sidebar while calling the dynamic_sidebar
output.
Updated to take widget index OR ID slug
function custom_output_widget( $sidebar_id, $widget_id ) {
global $custom_widget_target;
// if ( !$sidebar_id ) {
// $sidebars_widgets = get_option( 'sidebars_widgets' );
// print_r( $sidebars_widgets ); return;
// }
$custom_widget_target = array( 'sidebar' => $sidebar_id, 'widget' => $widget_id );
add_filter( 'sidebars_widgets', 'custom_widget_target_filter' );
dynamic_sidebar( $sidebar_id );
remove_filter( 'sidebars_widgets', 'custom_widget_target_filter' );
unset( $custom_widget_target );
}
function custom_widget_target_filter( $sidebars ) {
global $custom_widget_target;
if ( isset( $custom_widget_target) ) {
foreach ( $sidebars as $sidebar_id => $widgets ) {
if ( ( count( $widgets ) > 0 ) && ( $sidebar_id == $custom_widget_target['sidebar'] ) ) {
foreach ( $widgets as $i => $widget ) {
// echo '*' . $i . ' - ' . $widget . '*';
if ( ( $widget !== $custom_widget_target['widget'] ) && ( $i !== $custom_widget_target['widget'] ) ) {
unset( $widgets[$i] );
}
}
}
$sidebars[$sidebar_id] = $widgets;
}
}
return $sidebars;
}
// example based on widgets in original question
custom_output_widget( 'test_w', 'adni_widgets-93' );
Updated and simplified with closure (takes widget slug:)
function display_widget_wpse( $s_id, $w_id ) {
add_filter( 'sidebars_widgets', $callback = function( $widgets ) use ($s_id, $w_id) {
return array ( $s_id => array_filter (
$widgets[$s_id] ?? array(),
function ( $widget ) use ( $w_id ) { return $w_id === $widget; }
) );
} );
dynamic_sidebar( $s_id );
remove_filter( 'sidebars_widgets', $callback );
}