Display list of tags as drop down menu or radio buttons in a meta box?

I would like to group posts of a custom post type based on tags, but the default functionality does not do for the project I am working on.

I want the user to be able to select only one tag, not multiple tags, from a list of all the tags entered for that custom post type (drop down or radio buttons).

Read More

The user can create as many tags as he wants from the page for adding a custom taxonomy, and all these tags will be listed in the meta box on the single custom post page.

Any suggestion?

Related posts

Leave a Reply

4 comments

  1. In my last project i had the same issue and i just used this:

    first get the list of tags to a var using the get_categories function by passing the right taxonomy like this:

        $args = array(
    
        'orderby'                  => 'name',
        'order'                    => 'ASC',
        'hide_empty'               => 0,
        'taxonomy'                 => 'post_tag'
        );
    $categories=get_categories($args);
        foreach($categories as $category) { 
        $tags[] =  $category->name ;  
        }
    

    then create the arguments for the meta box

    $prefix = 'CPT_my_meta';
    $meta_box = array(
        'id' => 'custom-meta-box',
        'title' => 'tags',
        'page' => 'CPT name',
        'context' => 'normal',
        'priority' => 'high',
        'fields' => array(
            array(
                'name' => 'tags',
                'desc' => 'select a tag',
                'id' => $prefix . 'name',
                'type' => 'select',
                'options' => $tags
            )))
    

    then add the meta box

    add_action('admin_menu', 'add_my_box');
    
    // Add meta box
    function add_my_box() {
        global $meta_box;
    
        add_meta_box($meta_box['id'], $meta_box['title'], 'metabox_callback', $meta_box['page'], $meta_box['context'], $meta_box['priority']);
    }
    

    then all you have to do is create a function to show the meta box

    //show meta box
    function metabox_callback(){
    global $meta_box, $post;
    
        // Use nonce for verification
        echo '<input type="hidden" name="META_BOX_NONEC" value="', wp_create_nonce(basename(__FILE__)), '" />';
    
        echo '<table class="form-table">';
    
        foreach ($meta_box['fields'] as $field) {
            // get current post meta data
            $meta = get_post_meta($post->ID, $field['id'], true);
    
            echo '<tr>',
                    '<th style="width:20%"><label for="', $field['id'], '">', $field['name'], '</label></th>',
                    '<td>';
            switch ($field['type']) {
                case 'select':
                    echo '<select name="', $field['id'], '" id="', $field['id'], '">';
                    foreach ($field['options'] as $option) {
                        echo '<option', $meta == $option ? ' selected="selected"' : '', '>', $option, '</option>';
                    }
                    echo '</select>';
                    break;
            }
            echo    '</td></tr>';
        }
        echo '</table>';
    }
    

    and save it on post save

    //hook save function
    add_action('save_post', 'save_my_meta_box');
    
    // Save data from meta box
    function save_my_meta_box($post_id) {
        global $meta_box;
    
        // verify nonce
        if (!wp_verify_nonce($_POST['META_BOX_NONEC'], basename(__FILE__))) {
            return $post_id;
        }
    
        // check autosave
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
            return $post_id;
        }
    
        // check permissions
        if ('page' == $_POST['post_type']) {
            if (!current_user_can('edit_page', $post_id)) {
                return $post_id;
            }
        } elseif (!current_user_can('edit_post', $post_id)) {
            return $post_id;
        }
    
        foreach ($meta_box['fields'] as $field) {
            $old = get_post_meta($post_id, $field['id'], true);
            $new = $_POST[$field['id']];
    
            if ($new && $new != $old) {
                update_post_meta($post_id, $field['id'], $new);
            } elseif ('' == $new && $old) {
                delete_post_meta($post_id, $field['id'], $old);
            }
        }
    }
    

    hope this helps

  2. I tried to show the list and it does work if you use post_tag or category, but it gives me the list of the default post type tags or categories.

    I want to have the list of the custom taxonomies for my custom posts.
    My custom post type is “au-gallery” and my custom taxonomy is “gallery” therefore I tried

    $args = array(
    'type' => 'au-gallery',
    'orderby' => 'name',
    'order' => 'ASC',
    'hide_empty' => 0,
    'taxonomy' => 'gallery'
    );

    but I got only an empty list.

    I had a look at get_the_term_list and get_the_terms but those functions requires the post ID so…do I need to run a loop for al my custom posts to get this list or is there a better way??

  3. For custom taxonomies, I found a solution without writing a save_post hook.
    When register a taxonomy, need to specify 'meta_box_cb' => 'single_taxonomy_select_meta_box'

    For more details, please download this gist

    /**
     * Meta box to select only one taxonomy value
     *
     * @param WP_Post $post
     * @param array   $box
     */
    function single_taxonomy_select_meta_box( WP_Post $post, Array $box ) {
    
    $taxonomy = $box['args']['taxonomy'];
    
    $term_name_of_the_current_post = wp_get_object_terms( $post->ID, $taxonomy, [ 'fields' => 'names' ] )[0];
    
    $all_term_names = get_terms( $taxonomy, [ 'fields' => 'names', 'hide_empty' => false ] );
    ?>
    <label>
        <?php esc_html_e( 'Please choose:' ); ?>
        <select name="tax_input[<?php echo esc_attr( $taxonomy ); ?>]">
            <?php foreach ( $all_term_names as $term_name ) : ?>
                <option <?php selected( $term_name_of_the_current_post, $term_name ); ?>>
                    <?php echo esc_html( $term_name ); ?>
                </option>
            <?php endforeach; ?>
        </select>
    </label>
    

  4. If you want to show all the tags in the select box dropdown and also want to select the current tag should be on top in the select box

    And also you will move to the tag page while selecting the tag from the select box

    <select name="tags" id="tags" onchange="location = this.value;">
    
    <?php
    $tags = get_tags();
    $query = new WP_Term_Query(array(
        'object_ids' =>  get_the_ID(),
        'fields'     => 'ids',
    ));
    
    $tag_id = get_queried_object()->term_id;
    if ( $tags ) {
        foreach ( $tags as $tag ) {
        
            $selected= ( $tag->term_id == $tag_id )?'selected':'';
            printf('<option %1$s value="%2$s">%3$s</option>',
                $selected,
                get_tag_link( $tag->term_id ),
                $tag->name
            );
        
        }
    }
    ?>
    
    </select>