Actually <option> field doesn’t work with any CSS. So WordPress Developers/Designers did a simple yet nice trick for the nesting layout for <option> fields.
Actually in your inspection you missed something there:
<select name="page_id" id="page_id">
<option value="1" class="level-0">Level 0</option>
<option value="2" class="level-1"> Level 1</option>
<option value="3" class="level-1"> Level 1</option>
<option value="4" class="level-2"> Level 2</option>
<option value="5" class="level-3"> Level 3</option>
<option value="6" class="level-2"> Level 2</option>
<option value="7" class="level-3"> Level 3</option>
</select>
Have you noted the population of (HTML special character for spaces) there?
That is what creating the nesting look.
Let’s get the hand dirty
- In WordPress
wp-includes/folder, open the filepost-template.php. - Now find
wp_dropdown_pages(, so that you can find the function showing the dropdown (Line #1016 in WP 4.3.1) - In that function you will see another function is functioning there:
walk_page_dropdown_tree(, search for that one. (Line #1309 in WP 4.3.1) - In that function you will see a Walker Class is functioning there,
Walker_PageDropdown, find that class now. (Line #1471 in WP 4.3.1) - In that class you will see a function named
start_el, and within that function actually the trick is running.
Have you noticed that $pad variable there?
$pad = str_repeat(' ', $depth * 3);
Passing the $depth of the page, this str_repeat() is actually populating the spaces ( ) there. str_repeat() is a PHP function that repeats a string for specified times. And it’s working simply multiplying 3 times to the $depth. And that’s the trick.
Let’s do it
Now let us implement the similar thing in your case:
$_pages = get_pages( array( 'post_type'=> 'your_hierachical_cpt' ) );
<select name="my_field" id="my-field">
<?php foreach ($_pages as $_page) {
$depth = count( get_post_ancestors( $_page->ID ) ); //page_depth
$pad = str_repeat(' ', $depth * 3);
echo '<option value="'. $_page->ID .'" class="level-'. $depth .'">'. $pad . $_page->post_title .'</option>';
} ?>
</select>
We’re having all the pages in $_pages, having each of their depth in $depth, and then following that simple trick, in $pad. And when showing <option>s, we are showing the $depth classes, and adding the $pad variable just before options’ texts.
Yay! 😀
