I need a way to filter the titles in the page parent dropdown on the editor page

I suppose you aren’t still looking for this, but I was, and I managed to figure out a solution. I’m posting it up here as this came up pretty high in the search results.

What I did was to filter on the dropdown box generator for WordPress.

It passes in an array of args. One is the id of the select element, which for that part of the page is parent_id, and it also passes in the post_type so I restricted that to the post type I wanted to modify.

The technique is then to modify the array of WP_Query objects with a new title.

Unfortunately, by the time this filter is called, the full html markup is generated for the select box, so what I did was to just grab that snippet of html out of the WordPress core and put it into my filter. That way it would regenerate it with my modified WP_Query objects.

function customise_parent_page_dropdown($output, $parsed_args, $pages)
{
// CUSTOMISE HERE TO FILTER TO THE POST_TYPE YOU WANT
    if("parent_id" === $parsed_args['id'] && "mix-question" === $parsed_args['post_type']) {
        // update the page titles
        foreach($pages as $key => $page){
// CUSTOMISE HERE TO ALTER THE TITLE HOW YOU WANT
            $previous_answer = get_field('previous_answer', $pages[$key]->ID);
            if($previous_answer !== "") {
                $pages[$key]->post_title = $previous_answer . " – " . $pages[$key]->post_title;
            }
        }

        // regenerate the select tag - clone of the wordpress core code
        // https://github.com/WordPress/WordPress/blob/d5b8d282e8c03929aafb1fa660181b7db9ad55d3/wp-includes/post-template.php#L1187
        if ( ! empty( $pages ) ) {
            $class="";
            if ( ! empty( $parsed_args['class'] ) ) {
                $class = " class="" . esc_attr( $parsed_args["class'] ) . "'";
            }
    
            $output = "<select name="" . esc_attr( $parsed_args["name'] ) . "'" . $class . " id='" . esc_attr( $parsed_args['id'] ) . "'>\n";
            if ( $parsed_args['show_option_no_change'] ) {
                $output .= "\t<option value=\"-1\">" . $parsed_args['show_option_no_change'] . "</option>\n";
            }
            if ( $parsed_args['show_option_none'] ) {
                $output .= "\t<option value=\"" . esc_attr( $parsed_args['option_none_value'] ) . '">' . $parsed_args['show_option_none'] . "</option>\n";
            }
            $output .= walk_page_dropdown_tree( $pages, $parsed_args['depth'], $parsed_args );
            $output .= "</select>\n";
        }
    }

    return $output;
}
add_filter('wp_dropdown_pages', 'customise_parent_page_dropdown', 100, 3);

In my example code I’m pulling in an ACF field that I wanted to prefix it with. Change this to whatever you want.

Potential pitfalls with this approach are that if somebody calls the dropdown generator on this post type with an id of parent_id it will match and filter.

Also if WordPress changes the way it generates the select tag in the future then it will need to be updated here as well. I think these are reasonable trade-offs for getting the solution I wanted.