How to use the “multiple” attribute with wp_dropdown_pages

Out-of-the-box the WordPress function wp_dropdown_pages() does not support the multiple attribute. Luckily it’s not that hard to do and even better: you don’t need to do too much hacking to achieve this.

selectmultiple
Select list with multiple selected items generated with the wp_dropdown_pages() function.

The codex does not mention the walker option but it is possible to pass a Walker object in the wp_dropdown_pages() argument list. We will need to customize the Walker object in order to get the functionality we want.

When customizing the Walker implementation we simply extend the original Walker_PageDropdown class and do slight adjustments to it so it will respect multiple selected values.

The theme file functions.php could be a good place to define the class; or even in its own plugin.

Implementation of our Walker extension Walker_PageDropdown_Multiple:

<?php
if ( !class_exists( 'Walker_PageDropdown_Multiple' ) ) {
	/**
	 * Create HTML dropdown list of pages.
	 *
	 * @package WordPress
	 * @since 2.1.0
	 * @uses Walker
	 */
	class Walker_PageDropdown_Multiple extends Walker_PageDropdown {
		/**
		 * @see Walker::start_el()
		 * @since 2.1.0
		 *
		 * @param string $output Passed by reference. Used to append additional content.
		 * @param object $page Page data object.
		 * @param int $depth Depth of page in reference to parent pages. Used for padding.
		 * @param array $args Uses 'selected' argument for selected page to set selected HTML attribute for option element.
		 * @param int $id
		 */
		function start_el(&$output, $page, $depth, $args, $id = 0) {
			$pad = str_repeat( isset( $args['pad'] ) ? $args['pad'] : '--', $depth );

			$output .= "\t<option class=\"level-$depth\" value=\"$page->ID\"";
			if ( in_array( $page->ID, (array) $args['selected'] ) )
				$output .= ' selected="selected"';
			$output .= '>';
			$title = apply_filters( 'list_pages', $page->post_title, $page );
			$title = apply_filters( 'pagedropdown_multiple_title', $title, $page, $args );
			$output .= $pad . ' ' . esc_html( $title );
			$output .= "</option>\n";
		}
	}
}
?>


Now you’re all set to use the wp_dropdown_pages() function with multiple selected values.

Usage example:

<?php 

$selected = array( 1, 2, 3 );

$args = array(
	'echo' => 0,
	'walker' => new Walker_PageDropdown_Multiple(), // be sure to pass an instance of our new Walker class
	'selected' => $selected // The selected option can now be an array as well as a string
);

$pagesDropdown = wp_dropdown_pages( $args );

// Remove the wrapping select tag from the options so we can use
// our own select tag with the multiple attribute
$options = preg_replace( '#^\s*<select[^>]*>#', '', $pagesDropdown );
$options = preg_replace( '#</select>\s*$#', '', $options );
?>

<select name="my-multiple-valued-select" multiple="multiple">
	<?php echo $options; ?>
</select>

Bonus feature: You can change the “padding” string with the unofficial pad option. In my implementation it defaults to two hyphens per level (–).

This entry was posted in Wordpress and tagged , . Bookmark the permalink.
  • NJ Louch

    Using this within an settings screen, it only seems to submit one of the values.