Opened 7 years ago
Last modified 4 years ago
#41857 new defect (bug)
Walker_PageDropdown doesn't set correct selected value when using value_field
Reported by: | it4life | Owned by: | |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | normal | Version: | 4.8.1 |
Component: | Posts, Post Types | Keywords: | |
Focuses: | Cc: |
Description
If the value_field is different from ID, the selected value was not set.
Function Walker_PageDropdown::start_el
if ( $page->ID == $args['selected'] ) $output .= ' selected="selected"';
See also #32330
Change History (5)
#2
in reply to:
↑ 1
@
7 years ago
Replying to birgire:
Welcome to WordPress Trac, @it4life
Can you give an example?
Not all fields have unique values, like
ID
andpost_name
.
How should non-unique fields be handled?
If the first match is selected, then that would depend on the order - that might be problematic.
Yes, an example is using with value_field
= post_name
and it doesn't show selected value, as you see the code is only checking selected value by ID
.
#3
in reply to:
↑ 1
@
7 years ago
Replying to birgire:
Not all fields have unique values, like
ID
andpost_name
.
How should non-unique fields be handled?
If the first match is selected, then that would depend on the order - that might be problematic.
About unique field, I have idea to pass selected
and value_field
as callback:
<?php class Custom_Walker_PageDropdown extends Walker_PageDropdown { /** * Starts the element output. * @param array|string $args { * * @type int|string|callable $selected Value of the option that should be selected. * Default 0. * Or a callback that return true/false. * @type string|callable $value_field Post field or a callback used to populate * the 'value' attribute of the option elements. * Default 'ID'. * * @see Walker_PageDropdown */ public function start_el( &$output, $page, $depth = 0, $args = array(), $id = 0 ) { $pad = str_repeat(' ', $depth * 3); $value = $page->ID; if ( isset( $args['value_field'] ) ) { $value_field = $args['value_field']; if ( is_callable( $value_field ) ) { $value = call_user_func( $value_field, $page ); } elseif ( isset( $page->{$value_field} ) ) { $value = $page->{$value_field}; } } $output .= "\t<option class=\"level-$depth\" value=\"" . esc_attr( $value ) . "\""; if ( isset( $args['selected'] ) ) { $selected = $args['selected']; $is_selected = false; if ( is_callable( $selected ) ) { $is_selected = call_user_func( $selected, $page ); } else { $is_selected = ( $value == $selected ); } if ( $is_selected ) { $output .= ' selected="selected"'; } } $output .= '>'; $title = $page->post_title; if ( '' === $title ) { /* translators: %d: ID of a post */ $title = sprintf( __( '#%d (no title)' ), $page->ID ); } /** * Filters the page title when creating an HTML drop-down list of pages. * * @since 3.1.0 * * @param string $title Page title. * @param object $page Page data object. */ $title = apply_filters( 'list_pages', $title, $page ); $output .= $pad . esc_html( $title ); $output .= "</option>\n"; } }
Usage:
<?php wp_dropdown_pages( [ 'value_field' => function ( $page ) { return $page->ID . ' - ' . $page->post_name; }, 'selected' => function ( $page ) { return $page->post_name == 'blog'; }, 'walker' => new Custom_Walker_PageDropdown, ] );
What do you think?
#4
@
7 years ago
Thanks for the example.
What do you think?
I think it's a cool idea, worth exploring ;-)
But with this callback power, comes a great responsibility, like being sure that it's an injective map ;-)
Alternative (smaller step) approach, would be to add a support for a post_name
selection.
#5
@
4 years ago
I arrived here because of this issue, as the wp_dropdown_pages cannot set selected when value_field is other than the ID.
After reading the discussion above, about the possibility of using fields with non-unique values, then there are 2 options here:
Either, the value_field makes no real sense to exist as an option, or since it's there, then it should give the freedom to the developer to decide how to use it: I mean with what field as default value. In that case something like below would do the job:
if ( $page->{$args['value_field']} == $args['selected'] ) { $output .= ' selected="selected"'; }
Welcome to WordPress Trac, @it4life
Can you give an example?
Not all fields have unique values, like
ID
andpost_name
.How should non-unique fields be handled?
If the first match is selected, then that would depend on the order - that might be problematic.