• Resolved Luismin

    (@luismin)


    Hi commnunity!

    In my WordPress backend I have some custom posts and, in one of them, I want to display in a dropdown field some posts related with but ordered by post type. I want to display something like this.

    <select multiple="multiple" style="height:200px; width:300px"> <optgroup label="Productos"> <option>Producto 1</option> <option>Producto 2</option> <option>Producto 3</option> <option>Producto 4</option> <option>Producto 5</option> <option>Producto 6</option> </optgroup> <optgroup label="Paso 1"> <option>Subpagina 1</option> <option>Subpagina 2</option> <option>Subpagina 3</option> </optgroup> </optgroup> <optgroup label="Paso 2"> <option>Subpagina 1</option> <option>Subpagina 2</option> <option>Subpagina 3</option> </optgroup> </optgroup> <optgroup label="Paso 3"> <option>Subpagina 1</option> <option>Subpagina 2</option> <option>Subpagina 3</option> </optgroup> </select>

    Here is the code that displays all of posts that I want but without order. I figure out that I have to use the id of the custom post type but I do not how to, any idea?

    Note: I`ll like to save more than one post at the same time.

    // Add the Meta Box  
    
    function add_custom_meta_box_related() {
        add_meta_box(
            'custom_meta_box_related', // $id
            'Related Information', // $title
            'show_custom_meta_box_related', // $callback
            'related', // $page
            'normal', // $context
            'high'); // $priority
    }
    add_action('add_meta_boxes', 'add_custom_meta_box_related');
    
        // Field Array
        $prefix_related = 'custom_';
        $custom_meta_fields_related = array(  
    
    		array(
    			'label' => 'Related Items',
    			'desc' => 'Select a related item(s)',
    			'id'    =>  $prefix_materiales.'post_id',
    			'type' => 'post_list',
    			'post_type' => array('products','paso1','paso2','paso3','paso4','compra'),
    )
        );  
    
    	// The Callback
    function show_custom_meta_box_related() {
    global $custom_meta_fields_related, $post;
    // Use nonce for verification
    echo '<input type="hidden" name="custom_meta_box_nonce" value="'.wp_create_nonce(basename(__FILE__)).'" />';  
    
        // Begin the field table and loop
        echo '<table class="form-table">';
        foreach ($custom_meta_fields_related as $field_related) {
            // get value of this field if it exists for this post
            $meta_related = get_post_meta($post->ID, $field_related['id'], true);
            // begin a table row with
            echo '<tr>
                    <th><label for="'.$field_related['id'].'">'.$field_related['label'].'</label></th>
                    <td>';
                    switch($field_related['type']) {
                        // case items will go here 
    
    					// post_list
    					case 'post_list':
    					$items = get_posts( array (
    						'post_type' => $field_related['post_type'],
    						'posts_per_page' => -1
    					));
    					echo '<select multiple name="'.$field_related['id'].'" id="'.$field_related['id'].'">
    					<option value="">Select One or more</option>'; // Select One
    					foreach($items as $item) {
    						echo '<option value="'.$item->ID.'"',$meta_related == $item->ID ? ' selected="selected"' : '','> '.$item->post_title.'</option>';
    					} // end foreach
    					echo '</select><br /><span class="description">'.$field_related['desc'].'</span>';
    					break;
                    } //end switch
            echo '</td></tr>';
        } // end foreach
        echo '</table>'; // end table
    }
    
    // Save the Data
    function save_custom_meta_related($post_id) {
        global $custom_meta_fields_related;  
    
        // verify nonce
        if (!wp_verify_nonce($_POST['custom_meta_box_nonce'], 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;
        }  
    
        // loop through fields and save the data
        foreach ($custom_meta_fields_related as $field_related) {
            $old = get_post_meta($post_id, $field_related['id'], true);
            $new = $_POST[$field_related['id']];
            if ($new && $new != $old) {
                update_post_meta($post_id, $field_related['id'], $new);
            } elseif ('' == $new && $old) {
                delete_post_meta($post_id, $field_related['id'], $old);
            }
        } // end foreach
    }
    add_action('save_post', 'save_custom_meta_related');

    Thanks in advance

Viewing 15 replies - 1 through 15 (of 15 total)
  • Moderator bcworkz

    (@bcworkz)

    To order by post id, add 'orderby'=>'ID', to the get_posts() argument array. This may currently work because of the order in which you created the posts, but ID is the incorrect field to orderby post type. To properly order by post type, you cannot simply change ‘ID’ to ‘post_type’, it is not a supported value. Instead you must hook the filter ‘posts_orderby’.

    Your filter callback must verify the filter fired for the particular get_posts() call we are interested in, and only then return ‘post_type’.

    Thread Starter Luismin

    (@luismin)

    Thanks bcworkz!

    I solved part of the problem modifying this part of the code:

    // post_list
    case 'post_list':
    echo '<select multiple style="height:200px; width:300px" name="'.$field_related['id'].'" id="'.$field_related['id'].'">';
    echo '<option value=""></option>'; // Select One
    					foreach($field_related['post_type'] as $tipo_post){
    $items = get_posts( array (
    'post_type' => $tipo_post,
    'posts_per_page' => -1
    ));
    foreach($items as $item) {
    echo '<option value="'.$item->ID.'"',$meta_related == $item->ID ? ' selected="selected"' : '','> '.$tipo_post.'-'.
    $item->post_title. '</option>';
    } // end foreach
    
    }
    echo '</select><br /><span class="description">'.$field_related['desc'].'</span>';
    break;

    Now, the dropdown shows the type posts and their posts. The last thing will be display them in a select checkbox, like the category form from WordPress but inside a select and allow multiple selections. My brain burns…

    Any idea?

    Moderator bcworkz

    (@bcworkz)

    I’m glad you found a workable solution!

    Now you want a checkbox to appear next to each item in a dropdown list? I’ve never seen this variation and believe it is not possible using HTML form elements. You should be able to make multiple selections in your dropdown as is by Ctrl-clicking each item desired.

    Or do I misunderstand? Can you link to an example of what you are trying to do?

    Thread Starter Luismin

    (@luismin)

    I want to do something like this:

    https://www.gcooler.com/uploadfile/favorites/demo/dropdown-check-list.0.9/demo.html

    At this moment, by Ctrl-cliking I can select multiple options but only save the last one ??

    Moderator bcworkz

    (@bcworkz)

    Clever plugin that!

    You could go ahead and use that of course, but you’ll still have the same problem of only the last selection being saved. This has to do with the way PHP processes form submits. You need to set the select name attribute as an array by adding square brackets ‘[]’ so the values are accumulated in an array instead of being overwritten with each iteration. So your select tag should end up looking something like this:
    <select multiple style="height:200px; width:300px" name="fieldid[]" id="fieldid[]">

    Now all the selections will be available in $_POST[‘fieldid’] as an array instead of a single value. This little trick is not well documented, but many have been confused by this and a quick search brought up lots of questions and answers about it. (I just learned of it myself, so thanks for forcing me to learn something ?? )

    Thread Starter Luismin

    (@luismin)

    Hi bcworkz!!

    I’m glad you learn something new!! hehehehehe

    I understand what your are saying but, If you have a look to my code, you can see that:

    name="'.$field_related['id'].'" id="'.$field_related['id'].'">

    fieldid it will be 'id' => $prefix_related.'post_id' isn′t it?

    So, how can we put the field id inside name and id select?

    I′m confussing!!!!

    Moderator bcworkz

    (@bcworkz)

    Sorry I wasn’t more clear, I was trying to avoid using my feeble brain power to parse your code (i.e. I was being lazy)

    Try this:
    name="'.$field_related['id'].'[]" id="'.$field_related['id'].'[]">

    Check your form’s source html in your browser to see what all this code ends up looking like.

    Thread Starter Luismin

    (@luismin)

    It does not work grrrr. I’ll try to find the correct way but now I understand more or less hehehehe.

    Thanks bcworkz!

    If you find something new tell me!!!!

    Thread Starter Luismin

    (@luismin)

    Other posibility is to show checkboxes instead of select dropdown and with CSS put a scroll bar…

    Moderator bcworkz

    (@bcworkz)

    Hi Luismin,

    I saw your more recent question related to this. I’m replying here so no one is discouraged from answering in your other thread.

    There’s no easy function like wp_category_checklist for posts. It would only do what you have already done anyway, use get_posts() and step through the results to generate a form list. You still need to process the results correctly, which is where your problem lies, I believe.

    If your checkboxes have the same name, you still have the same problem of each iteration overwriting the previous values unless you append ‘[]’ to the name. At least with checkboxes you have the opportunity to use different names.

    If you are having difficulty and cannot determine where the problem lies, I would suggest breaking your project into smaller more manageable parts and testing each part before incrementally adding functioning parts together. You can create independent WP test pages by making new PHP files that you request directly from your browser. The page must include wp-load.php so WP functions and the DB are accessible by the page. Get your form working and the processing of the submission working on such test pages before attempting to include it in a meta box.

    In a similar vein, get your own meta box working on a very simple level, such as a single hard coded check box where only checked or not checked is stored in meta. When all the small elements are working, add them together one by one. I’ve found this approach much more productive than coding the whole project at once and then attempting to debug the whole thing.

    Thread Starter Luismin

    (@luismin)

    Thanks again bcworkz!

    This weekend I’ll solve the problem hehehehe. So optimistic!!!

    I publish the answer.

    Thread Starter Luismin

    (@luismin)

    Solved!!!!!

    // post_list
    case 'post_list_produktkrav': 
    
    $items = get_posts( array (
    								'post_type' => $field['post_type'],
    								'posts_per_page' => -1
    ));
    foreach($items as $item) {
    echo '<input type="checkbox" value="'.$item->ID.'" name="'.$field_related['id'].'[]" id="'.$item->ID.'"',$meta_related && in_array($item->ID, $meta_related) ? ' checked="checked"' : '',' />
    <label for="'.$item->ID.'">'.$item->post_title.'</label><br />';
    } // end foreach
    
    break;
    Thread Starter Luismin

    (@luismin)

    I put checkboxes instead of select dropdown.

    Moderator bcworkz

    (@bcworkz)

    Good work! Isn’t strange that often, after so much struggle, the resulting code is so simple?

    Thread Starter Luismin

    (@luismin)

    Yeeeah! Hehhehehe I’m ready for the next problem ??

    See u bcworkz.

Viewing 15 replies - 1 through 15 (of 15 total)
  • The topic ‘Order posts by custom post type in dropdown field’ is closed to new replies.