0

I am building a custom widget for my custom taxonomy and custom post type. basically it is a widget which displays recent posts from custom post type(game). I want to give the user an option to choose a term from which he want to display the custom posts. I have placed a drop-down list with all the custom terms available for my custom post type. But the problem is when user selects a term from the list, the drop-down instance $instance( cat_drop ) does not returne any value. what i will do is i will get this value and make a custom query to return all the posts from the selected term. following is my code.

    function get_all_terms(){
            $args = array(
                'taxonomy'           => 'gamecategory',
                'hide_empty'         => 0,
                'orderby'            => 'name',
                'order'              => 'ASC',
                'show_count'         => 0,
                'use_desc_for_title' => 0,
                'title_li'           => 0,
                'style'              => '',
                'echo'               => false,
            );
            $categories = wp_list_categories($args);
            if ( $categories ) {    
               // printf( '<div class="col">%s</div>', $categories );
            }
        return $categories;

        }

        /**
         * Adds Latest Games widget.
         */
        class latest_games_widget extends WP_Widget {

            /**
             * Register widget with WordPress.
             */
            function __construct() {
                parent::__construct(
                    'latest_games_widget', // Base ID
                    esc_html__( 'Latest Games', 'prisma' ), // Name
                    array( 'description' => esc_html__( 'Most Recent Games', 'text_domain' ), ) // Args
                );
            }

            /**
             * Front-end display of widget.
             */
            public function widget( $args, $instance ) {
                echo $args['before_widget'];
                if ( ! empty( $instance['title'] ) ) {
                    echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title'];
                }
                //Widget Content
                $selected_cat = $instance['cat_drop'];

                $args = array('post_type' => 'game', 'gamecategory' =>$selected_cat);
                $loop = new WP_Query($args);
                if($loop->have_posts(  )): 
                    while($loop->have_posts()): $loop->the_post();?>
                        <div class="col-md-3 game-card-outer">                   
                            <div class="game-card">
                                <?php if (has_post_thumbnail()): ?>
                                            <a href="<?php the_permalink();?>"><?php the_post_thumbnail('small', array('class' => 'aligncenter'));  ?></a>
                                <?php endif;?>

                                <a class="latest_games_widget_post_title" href="<?php the_permalink(); ?>"><?php the_title(); ?></a>

                            </div>
                        </div>                                
                   <?php endwhile;
                endif;

                //After Widget part
                echo $args['after_widget'];
            }                

            /**
             * Back-end widget form.
             *
             * @see WP_Widget::form()
             *
             * @param array $instance Previously saved values from database.
             */
            public function form( $instance ) {
                $title = ! empty( $instance['title'] ) ? $instance['title'] : esc_html__( '', 'prisma' );
                $cat_title = ! empty( $instance['cat_title'] ) ? $instance['cat_title'] : esc_html__( '', 'prisma' );
                ?>
                <select name="" id="<?php echo ( $this->get_field_id( 'cat_drop' ) ); ?>">
                            <?php $terms = get_terms(['taxonomy' => 'gamecategory','hide_empty' => false,]);foreach($terms as $item){?>
                                <option value="<?php echo $item->name;?>"><?php echo $item->name; ?></option>
                                <?php }?>
</select>        
                <p>
                <label for="<?php echo esc_attr( $this->get_field_id( 'cat_title' ) ); ?>"><?php esc_attr_e( 'Game category to Display:', 'prisma' ); ?></label> 
                <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'cat_title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'cat_title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
                </p>                
                <p>
                <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_attr_e( 'Widget Title:', 'prisma' ); ?></label> 
                <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
                </p>                                                        
                <?php 
            }                                                
            /**
             * Sanitize widget form values as they are saved.
             *
             * @see WP_Widget::update()
             *
             * @param array $new_instance Values just sent to be saved.
             * @param array $old_instance Previously saved values from database.
             *
             * @return array Updated safe values to be saved.
             */
            public function update( $new_instance, $old_instance ) {
                $instance = array();
                $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? sanitize_text_field( $new_instance['title'] ) : '';
                $instance['cat_title'] = ( ! empty( $new_instance['cat_title'] ) ) ? sanitize_text_field( $new_instance['cat_title'] ) : '';
    $instance[ 'cat_drop' ] = ( !empty( $new_instance[ 'cat_drop' ] ) ? strip_tags( $new_instance[ 'cat_drop' ] ) :  esc_html__('','prisma') );

                return $instance;
            }

        } // class Foo_Widget        

        // register Foo_Widget widget
        function register_foo_widget() {
            register_widget( 'latest_games_widget' );
        }
        add_action( 'widgets_init', 'register_foo_widget' );
1

The cat_drop setting is empty because your drop-down menu, or the select field doesn't have the proper name value, so PHP isn't receiving the selected option/value. So to fix the issue, just add the proper name value to the select field:

<!-- Wrapped for brevity. -->
<select
  name="<?php echo $this->get_field_name( 'cat_drop' ); ?>"
  id="<?php echo $this->get_field_id( 'cat_drop' ); ?>"
>

But then, there are other issues in your code:

  1. In the cat_drop drop-down menu, the options should be the term slug, but you currently set it to the term name. So be sure to use the term slug instead:

    <!-- Note the $item->slug -->
    <option value="<?php echo $item->slug;?>"><?php echo esc_html( $item->name ); ?></option>
    
  2. In the widget display callback (widget()), you're overriding the $args variable when you do $args = array('post_type' => 'game', 'gamecategory' =>$selected_cat); and that results in a PHP notice with the echo $args['after_widget']; at the end of the function, because the $args['after_widget'] is now undefined. And when it's undefined, the widget container will not be closed and that could result in layout issues, despite browsers are basically "smart" and would-auto close the container.

    So you should rename one of the $args, maybe the one that you use with WP_Query.

  3. Using esc_html__() on an empty string is pointless: esc_html__( '', 'prisma' ). So change those to just ''.

  4. This is just a personal note.. Could you please, improve the formatting of your code? E.g. Get rid of those unnecessary blank lines and use tab for indentation. Because a good code is not just one that works, but also clean because it would be easy for other developers to maintain or work with the code. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.