WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I know how to add a Walker to a custom menu created by the theme (menu named primary in this example), but how can I target a menu thats created in a widget with the default wordpress custom menu widget?

if ( has_nav_menu( 'primary' ) ) {

$args = array(
    'menu' => 'main-menu',
    'menu_id' => 'main-menu',
    'theme_location' => 'primary',
    'depth' => 0,
    'container' => false,
    'menu_class' => 'nav',
    'walker' => new Myprefix_Walker_Nav_Menu(),
    'echo' => 0

$nav = wp_nav_menu( $args );

share|improve this question
up vote 8 down vote accepted

If you look at implementation of WP_Nav_Menu_Widget class you will see the following code:

function widget($args, $instance) {
    // Get menu
    $nav_menu = ! empty( $instance['nav_menu'] ) ? wp_get_nav_menu_object( $instance['nav_menu'] ) : false;

    if ( !$nav_menu )

    $instance['title'] = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );

    echo $args['before_widget'];

    if ( !empty($instance['title']) )
        echo $args['before_title'] . $instance['title'] . $args['after_title'];

    wp_nav_menu( array( 'fallback_cb' => '', 'menu' => $nav_menu ) );

    echo $args['after_widget'];

It means that there is no any chance to hook a menu. So you need to take a look at wp_nav_menu function implementation, where you can find following lines of code:

$defaults = array( 'menu' => '', 'container' => 'div', 'container_class' => '', 'container_id' => '', 'menu_class' => 'menu', 'menu_id' => '',
'echo' => true, 'fallback_cb' => 'wp_page_menu', 'before' => '', 'after' => '', 'link_before' => '', 'link_after' => '', 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
'depth' => 0, 'walker' => '', 'theme_location' => '' );

$args = wp_parse_args( $args, $defaults );
$args = apply_filters( 'wp_nav_menu_args', $args );
$args = (object) $args;

Here you can see that all arguments passed to the wp_nav_menu function could be replaced. So what you need is to create your own hook handler which will add your walker to a navigation menu. It could be simple as:

function myplugin_custom_walker( $args ) {
    return array_merge( $args, array(
        'walker' => new My_Custom_Walker(),
        // another setting go here ... 
    ) );
add_filter( 'wp_nav_menu_args', 'myplugin_custom_walker' );
share|improve this answer
this is great thank you. Looks like this makes the default for all menus. Am I right to assume that when i use this i am stuck with all menus having this walker? because i tryed 'walker' => new Walker_Nav_Menu() in the arguments of my specific menu to override it again to become the wordpress default walker for just one menu, but sadly this don't works. – amy Jun 1 '12 at 16:57
@amy yes it will be default for all menus. – Eugene Manuilov Jun 1 '12 at 17:01
@amy you can include code to examine the args. Then put an if conditional whether you apply the walker or not. – Wayne Mar 7 '13 at 13:59

Expanding on @Eugene's answer, if you want to limit this to a specific menu, just check the term ID of the menu:

function custom_nav_args($args){
$menu = $args['menu'];
    if($menu->term_id === 17)  /* replace term_id with menu id, or use $menu->name to do it by menu name*/
        $args['walker'] = new My_Custom_Walker();
    return $args;
add_filter('wp_nav_menu_args', 'custom_nav_args');
share|improve this answer
How would we filter by sidebar id? – Steven Vachon Mar 3 at 19:33

Your Answer


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.