0

I have developed a widget to show latest news. The widget functionality is working correctly but the problem is the Widget title is not saving in backend. What is the right way to do it?

class infotravel_news_list_widget extends WP_Widget {
    public function __construct() {
        parent::__construct( false, $name = __( 'Latest News', 'infotravel' ) );
    }

    public function form( $instance ) {

        $defaults = array(
                'title' => '',
        );

        extract( wp_parse_args( array( $instance, $defaults ) ) );

        // Widget title ?>
        <p>
            <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php _e( 'Title', 'infotravel' ); ?></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( $defaults['title'] ); ?>" />
        </p>

        <?php
    }

    public function update( $new_instance, $old_instance ) {
        $instance = $old_instance;
        $instance['title'] = isset( $new_instance['title'] ) ? wp_strip_all_tags( $new_instance['title'] ) : '';

        return $instance;
    }

    public function widget( $args, $instance ) {
        $news_args = array(
            'post_type'      => 'infotravel_news',
            'posts_per_page' => 5,
            'post_status'    => 'publish',
            'orderby'        => 'post_date',
            'order'          => 'desc'
        );
        $query = new WP_Query( $news_args );

        if( $query -> have_posts() ) :
            while( $query -> have_posts() ) : $query -> the_post(); ?>
                <h3><?php the_title(); ?></h3>
            <?php
            endwhile;
        endif;
    ?>

    <?php }
}

add_action( 'widgets_init', function(){
    register_widget( 'infotravel_news_list_widget' );
} );

1 Answer 1

1

It's because you're always outputting the default value into the input, regardless of what the saved value is:

<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( $defaults['title'] ); ?>" />

Specifically:

value="<?php echo esc_attr( $defaults['title'] ); ?>"

$defaults['title'] is always going to be an empty string. The saved title is inside $instance['title'], and, because of this line:

extract( wp_parse_args( array( $instance, $defaults ) ) );

It is also inside a variable called $title. This isn't immediately obvious, which is why using extract() like this is bad practice.

I suggest either setting the variables explicitly:

$title = isset( $instance['title'] ) ? $instance['title'] : $defaults['title']; 

In which case the value should be output like so:

value="<?php echo esc_attr( $title ); ?>"

Or putting the result of wp_parse_args() back into $instance:

public function form( $instance ) {
    $defaults = array(
        'title' => '',
    );

    $instance = wp_parse_args( array( $instance, $defaults ) );

    // ...etc.
}

In which case the value should be output like so:

value="<?php echo esc_attr( $instance['title'] ); ?>"
3
  • value="<?php echo esc_attr( $instance['title'] ); ?>" saved me! Thanks a lot :) Commented Sep 5, 2019 at 13:15
  • 1
    Just so you know, if you only change that line without the corresponding change with wp_parse_args() you will cause an error when the widget is first placed if debug mode is on. Commented Sep 5, 2019 at 14:05
  • I was having that issue actually. You again saved me :) Commented Sep 9, 2019 at 6:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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