Meta box controls — select and dropdowns

Last time I covered the input field, radio buttons and check boxes for your meta box custom controls. We are going to continue on the same path. Today we’ll be interested in adding select dropdowns in our meta box. The environment in which we are going to do this will be the same as last time, so if you are testing this out, simply add the new controls after the already existing ones, and you’ll be good to go.

PHP code

Assuming you have added the meta box (if, not just look at the last article), inside the mytheme_metabox_controls() function we’ll add the new controls.

if ( ! function_exists( 'mytheme_metabox_controls' ) ) {
/**
* Meta box render function
*
* @param object $post Post object.
* @since 1.0.0
*/
function mytheme_metabox_controls( $post ) {
$meta = get_post_meta( $post->ID );
$mytheme_input_field = ( isset( $meta['mytheme_input_field'][0] ) && '' !== $meta['mytheme_input_field'][0] ) ? $meta['mytheme_input_field'][0] : '';
$mytheme_radio_value = ( isset( $meta['mytheme_radio_value'][0] ) && '' !== $meta['mytheme_radio_value'][0] ) ? $meta['mytheme_radio_value'][0] : '';
$mytheme_checkbox_value = ( isset( $meta['mytheme_checkbox_value'][0] ) && '1' === $meta['mytheme_checkbox_value'][0] ) ? 1 : 0;
$mytheme_custom_select = ( isset( $meta['mytheme_custom_select'][0] ) && '' !== $meta['mytheme_custom_select'][0] ) ? $meta['mytheme_custom_select'][0] : '';
$mytheme_page_select = ( isset( $meta['mytheme_page_select'][0] ) && '' !== $meta['mytheme_page_select'][0] ) ? $meta['mytheme_page_select'][0] : '';
$mytheme_category_select = ( isset( $meta['mytheme_category_select'][0] ) && '' !== $meta['mytheme_category_select'][0] ) ? $meta['mytheme_category_select'][0] : '';

wp_nonce_field( 'mytheme_control_meta_box', 'mytheme_control_meta_box_nonce' ); // Always add nonce to your meta boxes!
?>
<style type="text/css">
.post_meta_extras p{margin: 20px;}
.post_meta_extras label{display:block; margin-bottom: 10px;}
</style>
<div class="post_meta_extras">
<p>
<label><?php esc_attr_e( 'Input text', 'mytheme' ); ?></label>
<input type="text" name="mytheme_input_field" value="<?php echo esc_attr( $mytheme_input_field ); ?>">
</p>
<p>
<label>
<input type="radio" name="mytheme_radio_value" value="value_1" <?php checked( $mytheme_radio_value, 'value_1' ); ?>>
<?php esc_attr_e( 'Radio value 1', 'mytheme' ); ?>
</label>
<label>
<input type="radio" name="mytheme_radio_value" value="value_2" <?php checked( $mytheme_radio_value, 'value_2' ); ?>>
<?php esc_attr_e( 'Radio value 2', 'mytheme' ); ?>
</label>
<label>
<input type="radio" name="mytheme_radio_value" value="value_3" <?php checked( $mytheme_radio_value, 'value_3' ); ?>>
<?php esc_attr_e( 'Radio value 3', 'mytheme' ); ?>
</label>
</p>
<p>
<label><input type="checkbox" name="mytheme_checkbox_value" value="1" <?php checked( $mytheme_checkbox_value, 1 ); ?> /><?php esc_attr_e( 'Checkbox value', 'mytheme' ); ?></label>
</p>
<p>
<label for="mytheme_custom_select"><?php esc_attr_e( 'Custom Select', 'mytheme' ); ?></label>
<select id="mytheme_custom_select" name="mytheme_custom_select">
<option value=""><?php esc_html_e( '&ndash; Select &ndash;', 'mytheme' ); ?></option>
<option value="<?php echo esc_attr( 'myvalue_1' ); ?>" <?php selected( $mytheme_custom_select, 'myvalue_1', true ); ?>><?php esc_html_e( 'My custom value 1', 'mytheme' ); ?></option>
<option value="<?php echo esc_attr( 'myvalue_2' ); ?>" <?php selected( $mytheme_custom_select, 'myvalue_2', true ); ?>><?php esc_html_e( 'My custom value 2', 'mytheme' ); ?></option>
<option value="<?php echo esc_attr( 'myvalue_3' ); ?>" <?php selected( $mytheme_custom_select, 'myvalue_3', true ); ?>><?php esc_html_e( 'My custom value 3', 'mytheme' ); ?></option>
</select>
</p>
<p>
<?php
$args_pages = array(
'depth' => 0,
'child_of' => 0,
'selected' => $mytheme_page_select,
'echo' => 1,
'name' => 'mytheme_page_select',
'id' => 'mytheme_page_select',
'class' => null,
'show_option_none' => null,
'show_option_no_change' => null,
'option_none_value' => esc_html__( '&ndash; Select &ndash;', 'mytheme' ),
);
?>
<label for="mytheme_page_select"><?php esc_attr_e( 'Pages Select', 'mytheme' ); ?></label>
<?php
wp_dropdown_pages( $args_pages );
?>
</p>
<p>
<?php $args_cat = array(
'show_option_all' => '',
'show_option_none' => '',
'option_none_value' => '-1',
'orderby' => 'ID',
'order' => 'ASC',
'show_count' => 0,
'hide_empty' => 1,
'child_of' => 0,
'exclude' => '',
'include' => '',
'echo' => 1,
'selected' => $mytheme_category_select,
'hierarchical' => 0,
'name' => 'mytheme_category_select',
'id' => 'mytheme_category_select',
'class' => 'postform',
'depth' => 0,
'tab_index' => 0,
'taxonomy' => 'category',
'hide_if_empty' => false,
'value_field' => 'term_id',
); ?>
<label for="mytheme_category_select"><?php esc_attr_e( 'Category Select', 'mytheme' ); ?></label>
<?php
wp_dropdown_categories( $args_cat );
?>
</p>
<?php
}
}

Here the things we’ve added are the new saved options

$mytheme_custom_select = ( isset( $meta['mytheme_custom_select'][0] ) && '' !== $meta['mytheme_custom_select'][0] ) ? $meta['mytheme_custom_select'][0] : '';
$mytheme_page_select = ( isset( $meta['mytheme_page_select'][0] ) && '' !== $meta['mytheme_page_select'][0] ) ? $meta['mytheme_page_select'][0] : '';
$mytheme_category_select = ( isset( $meta['mytheme_category_select'][0] ) && '' !== $meta['mytheme_category_select'][0] ) ? $meta['mytheme_category_select'][0] : '';

This is our check to see if we have anything saved in the database. You can even change the default values of these variables from empty to some value that you know can appear — certain page or a category ID, or a custom select value of your choice.

For custom select, we’ve populated the <select> HTML element with our own options. To have saved option displayed, or selected, we are using the built in function selected(). This function takes the saved value, and compares it to the value that is in the <option> element. The last argument, if set to true, will echo out the selected inside the option. The last argument is used if you want to use the selected function inside the return statement. In that case you can set it to false, so that it wouldn’t echo it out (because we don’t want echoing inside a return statement).

The next two functions we used are wp_dropdown_pages() and wp_dropdown_categories(). These built in functions will output selects with the pages or categories (taxonomies) that you want. The great thing about them is that you can customize them using the arguments array.
 In the case of our pages select, we want to make sure that the selected option will show — we set it to the saved meta value, and that we give it the name and id so that we can target the correct $_POST array key

<?php
$args_pages = array(
'depth' => 0,
'child_of' => 0,
'selected' => $mytheme_page_select,
'echo' => 1,
'name' => 'mytheme_page_select',
'id' => 'mytheme_page_select',
'class' => null,
'show_option_none' => null,
'show_option_no_change' => null,
'option_none_value' => esc_html__( '&ndash; Select &ndash;', 'mytheme' ),
);
?>
<label for="mytheme_page_select"><?php esc_attr_e( 'Pages Select', 'mytheme' ); ?></label>
<?php
wp_dropdown_pages( $args_pages );
?>

Similarly we do it for the categories

<?php $args_cat = array(
'show_option_all' => '',
'show_option_none' => '',
'option_none_value' => '-1',
'orderby' => 'ID',
'order' => 'ASC',
'show_count' => 0,
'hide_empty' => 1,
'child_of' => 0,
'exclude' => '',
'include' => '',
'echo' => 1,
'selected' => $mytheme_category_select,
'hierarchical' => 0,
'name' => 'mytheme_category_select',
'id' => 'mytheme_category_select',
'class' => 'postform',
'depth' => 0,
'tab_index' => 0,
'taxonomy' => 'category',
'hide_if_empty' => false,
'value_field' => 'term_id',
); ?>
<label for="mytheme_category_select"><?php esc_attr_e( 'Category Select', 'mytheme' ); ?></label>
<?php
wp_dropdown_categories( $args_cat );
?>

Saving the meta box

The last thing before completion is making sure that we have saved the selected options. In our mytheme_save_metaboxes() function

add_action( 'save_post', 'mytheme_save_metaboxes' );

if ( ! function_exists( 'mytheme_save_metaboxes' ) ) {
/**
* Save controls from the meta boxes
*
* @param int $post_id Current post id.
* @since 1.0.0
*/
function mytheme_save_metaboxes( $post_id ) {
/*
* We need to verify this came from the our screen and with proper authorization,
* because save_post can be triggered at other times. Add as many nonces, as you
* have metaboxes.
*/
if ( ! isset( $_POST['mytheme_control_meta_box_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['mytheme_control_meta_box_nonce'] ), 'mytheme_control_meta_box' ) ) { // Input var okay.
return $post_id;
}

// Check the user's permissions.
if ( isset( $_POST['post_type'] ) && 'page' === $_POST['post_type'] ) { // Input var okay.
if ( ! current_user_can( 'edit_page', $post_id ) ) {
return $post_id;
}
} else {
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
}

/*
* If this is an autosave, our form has not been submitted,
* so we don't want to do anything.
*/
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}

/* Ok to save */

if ( isset( $_POST['mytheme_input_field'] ) ) { // Input var okay.
update_post_meta( $post_id, 'mytheme_input_field', sanitize_text_field( wp_unslash( $_POST['mytheme_input_field'] ) ) ); // Input var okay.
}

if ( isset( $_POST['mytheme_radio_value'] ) ) { // Input var okay.
update_post_meta( $post_id, 'mytheme_radio_value', sanitize_text_field( wp_unslash( $_POST['mytheme_radio_value'] ) ) ); // Input var okay.
}

$mytheme_checkbox_value = ( isset( $_POST['mytheme_checkbox_value'] ) && '1' === $_POST['mytheme_checkbox_value'] ) ? 1 : 0; // Input var okay.
update_post_meta( $post_id, 'mytheme_checkbox_value', esc_attr( $mytheme_checkbox_value ) );

if ( isset( $_POST['mytheme_custom_select'] ) ) { // Input var okay.
update_post_meta( $post_id, 'mytheme_custom_select', sanitize_text_field( wp_unslash( $_POST['mytheme_custom_select'] ) ) ); // Input var okay.
}

if ( isset( $_POST['mytheme_page_select'] ) ) { // Input var okay.
update_post_meta( $post_id, 'mytheme_page_select', sanitize_text_field( wp_unslash( $_POST['mytheme_page_select'] ) ) ); // Input var okay.
}

if ( isset( $_POST['mytheme_category_select'] ) ) { // Input var okay.
update_post_meta( $post_id, 'mytheme_category_select', sanitize_text_field( wp_unslash( $_POST['mytheme_category_select'] ) ) ); // Input var okay.
}

}
}

Notice the last three save options. We just follow the same principle as with input field. In the end we are left with something that looks like the image below

Select control in meta box

Select control in meta box

Usage

Using the meta fields is the same as before. Just use get_post_meta() function like

$pages = get_post_meta( get_the_ID(), 'mytheme_page_select', true );

This will return the ID of the pages (or category), or the custom value from your custom select respectively. Just make sure you change the meta name.

This completes the second article in the series of meta box controls articles. In the next article I’ll cover the creation of image select, and gallery upload meta box controls, which can be useful in custom post types especially (in custom plugins). If you have any questions feel free to ask it in the comments below, and as always, happy coding :)


Originally published at Made by Denis.