WordPress: Create a Custom Widget (Part 2)
This entry is part of my WordPress development series, providing tutorials on specific things you can do in WordPress. Read some more?
In the second part of this tutorial, we are going to expand upon our basic custom widget we have already created by utilizing a simple form in the back-end. Unlike in the previous tutorial where each instance of the widget on our website displays the same, uneditable information, this widget will be able to have unique information for each instance of the widget placed throughout our website.
Create Our Widget
We begin much like we did in part 1 of this tutorial, by creating our own class that extends the WP_Widget
class in our functions.php file. This time I have called it My_Adv_Cat_Widget
.
<?php class My_Adv_Cat_Widget extends WP_Widget { // Create widget public function __construct() { parent::__construct( 'my_adv_cat_widget', // Base ID 'My Advanced Cat Widget', // Name array( 'description' => 'This is my advanced cat widget.') // Arguments ); } } ?>
We again give our widget a base ID, name, and description. Following this first section inside of our class, we add the code below for displaying our widget on the front-end of our website. We have more code inside the widget()
function this time because we will be gathering and displaying more information using the form we will create for the back-end.
The Front-End Display
<?php // Front-End Display of the Widget public function widget( $instance ) { // Saved widget options $title = apply_filters( 'widget_title', $instance['title'] ); $catName = $instance['cat_name']; $catAge = $instance['cat_age']; $favToy = $instance['fav_toy']; $desc = apply_filters( 'widget_textarea', empty( $instance['description'] ) ? '' : $instance['description'], $instance ); // Display information echo '<div class="my-widget block">'; if ( !empty( $title ) ) { echo '<h3>' . $title . '</h3>'; } if ( !empty( $catName ) ) { echo '<p><strong>Name:</strong> ' . $catName . '<br />'; } if ( !empty( $catAge ) ) { echo '<strong>Age:</strong> ' . $catAge . '<br />'; } if ( !empty( $favToy ) ) { echo '<strong>Favourite Toy:</strong> ' . $favToy . '</p>'; } if ( !empty( $desc ) ) { echo wpautop( $desc ); } echo '</div>'; } ?>
First we get the values of the saved form options, and store in variables. Below that, we display the values if they exist. For our description, since it is going to be a textarea, we are using the widget_textarea
filter and the wpautop()
function to save and display paragraphs from the textarea.
The Back-End Form
<?php // Back-end form of the Widget public function form( $instance ) { // Check for values if ( isset( $instance[ 'title' ] ) ) { $title = $instance[ 'title' ]; } if ( isset( $instance[ 'cat_name' ] ) ) { $catName = $instance[ 'cat_name' ]; } if ( isset( $instance[ 'cat_age' ] ) ) { $catAge = $instance[ 'cat_age' ]; } if ( isset( $instance[ 'fav_toy' ] ) ) { $favToy = $instance[ 'fav_toy' ]; } if ( isset( $instance[ 'description' ] ) ) { $desc = $instance[ 'description' ]; } ?> <p> <label for="<?php echo $this->get_field_id( 'title' ); ?>">Title:</label> <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>"> </p> <p> <label for="<?php echo $this->get_field_id( 'cat_name' ); ?>">Name:</label> <input class="widefat" id="<?php echo $this->get_field_id( 'cat_name' ); ?>" name="<?php echo $this->get_field_name( 'cat_name' ); ?>" type="text" value="<?php echo esc_attr( $catName ); ?>"> </p> <p> <label for="<?php echo $this->get_field_id( 'cat_age' ); ?>">Age:</label> <select class="widefat" id="<?php echo $this->get_field_id('cat_age'); ?>" name="<?php echo $this->get_field_name('cat_age'); ?>"> <?php $options = array( '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20' ); foreach ( $options as $option ) { echo '<option value="' . $option . '" id="' . $option . '"', $catAge == $option ? ' selected="selected"' : '', '>' . $option . '</option>'; } ?> </select> </p> <p> <label for="<?php echo $this->get_field_id( 'fav_toy' ); ?>">Favourite Toy:</label> <input class="widefat" id="<?php echo $this->get_field_id( 'fav_toy' ); ?>" name="<?php echo $this->get_field_name( 'fav_toy' ); ?>" type="text" value="<?php echo esc_attr( $favToy ); ?>"> </p> <p> <label for="<?php echo $this->get_field_id( 'description' ); ?>">Description:</label> <textarea class="widefat" id="<?php echo $this->get_field_id('description'); ?>" name="<?php echo $this->get_field_name('description'); ?>" rows="16" cols="20"><?php echo $desc; ?></textarea> </p> <?php } ?>
Next we add in the section for our admin back-end, the form()
function. Here we are using a few different form elements – inputs, a select, and a textarea.
First we begin by checking for the values of each of our form’s elements. If they have been set, we store these values in variables, which we then use to pre-populate the form elements. This is so when you go back to edit the widget at a later time, you will see the values in the form that were previously saved.
Below that is where we have the code for our form elements. We utilize the class widefat
from WordPress for consistent styling. get_field_id()
and get_field_name()
are used to get the ID and Name for each form element in this instance of the widget. Other elements can be added to widget forms, such as radio buttons and checkboxes.
In this last piece of our class, the update()
function, we sanitize and return the safe values of the form to be saved.
<?php // Sanitize and return the safe form values public function update( $new_instance, $old_instance ) { $instance = array(); $instance['title'] = ( !empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : ''; $instance['cat_name'] = ( !empty( $new_instance['cat_name'] ) ) ? strip_tags( $new_instance['cat_name'] ) : ''; $instance['cat_age'] = ( !empty( $new_instance['cat_age'] ) ) ? strip_tags( $new_instance['cat_age'] ) : ''; $instance['fav_toy'] = ( !empty( $new_instance['fav_toy'] ) ) ? strip_tags( $new_instance['fav_toy'] ) : ''; if ( current_user_can('unfiltered_html') ) { $instance['description'] = $new_instance['description']; } else { $instance['description'] = stripslashes( wp_filter_post_kses( addslashes($new_instance['description']) ) ); } return $instance; } ?>
Register Our Widget
As we did in part 1, we must register our widget.
<?php // Register widget add_action( 'widgets_init', function(){ register_widget( 'My_Adv_Cat_Widget' ); }); ?>
The Final Code
This is what my final code looks like:
<?php class My_Adv_Cat_Widget extends WP_Widget { // Create widget public function __construct() { parent::__construct( 'my_adv_cat_widget', // Base ID 'My Advanced Cat Widget', // Name array( 'description' => 'This is my advanced cat widget.') // Arguments ); } // Front-End Display of the Widget public function widget( $args, $instance ) { // Saved widget options $title = $instance['title']; $catName = $instance['cat_name']; $catAge = $instance['cat_age']; $favToy = $instance['fav_toy']; $desc = apply_filters( 'widget_textarea', empty( $instance['description'] ) ? '' : $instance['description'], $instance ); // Display information echo '<div class="my-widget block">'; if ( !empty( $title ) ) { echo '<h3>' . $title . '</h3>'; } if ( !empty( $catName ) ) { echo '<p><strong>Name:</strong> ' . $catName . '<br />'; } if ( !empty( $catAge ) ) { echo '<strong>Age:</strong> ' . $catAge . '<br />'; } if ( !empty( $favToy ) ) { echo '<strong>Favourite Toy:</strong> ' . $favToy . '</p>'; } if ( !empty( $desc ) ) { echo wpautop( $desc ); } echo '</div>'; } // Back-end form of the Widget public function form( $instance ) { // Check for values if ( isset( $instance[ 'title' ] ) ) { $title = $instance[ 'title' ]; } if ( isset( $instance[ 'cat_name' ] ) ) { $catName = $instance[ 'cat_name' ]; } if ( isset( $instance[ 'cat_age' ] ) ) { $catAge = $instance[ 'cat_age' ]; } if ( isset( $instance[ 'fav_toy' ] ) ) { $favToy = $instance[ 'fav_toy' ]; } if ( isset( $instance[ 'description' ] ) ) { $desc = $instance[ 'description' ]; } ?> <p> <label for="<?php echo $this->get_field_id( 'title' ); ?>">Title:</label> <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>"> </p> <p> <label for="<?php echo $this->get_field_id( 'cat_name' ); ?>">Name:</label> <input class="widefat" id="<?php echo $this->get_field_id( 'cat_name' ); ?>" name="<?php echo $this->get_field_name( 'cat_name' ); ?>" type="text" value="<?php echo esc_attr( $catName ); ?>"> </p> <p> <label for="<?php echo $this->get_field_id( 'cat_age' ); ?>">Age:</label> <select class="widefat" id="<?php echo $this->get_field_id('cat_age'); ?>" name="<?php echo $this->get_field_name('cat_age'); ?>"> <?php $options = array( '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20' ); foreach ( $options as $option ) { echo '<option value="' . $option . '" id="' . $option . '"', $catAge == $option ? ' selected="selected"' : '', '>' . $option . '</option>'; } ?> </select> </p> <p> <label for="<?php echo $this->get_field_id( 'fav_toy' ); ?>">Favourite Toy:</label> <input class="widefat" id="<?php echo $this->get_field_id( 'fav_toy' ); ?>" name="<?php echo $this->get_field_name( 'fav_toy' ); ?>" type="text" value="<?php echo esc_attr( $favToy ); ?>"> </p> <p> <label for="<?php echo $this->get_field_id( 'description' ); ?>">Description:</label> <textarea class="widefat" id="<?php echo $this->get_field_id('description'); ?>" name="<?php echo $this->get_field_name('description'); ?>" rows="16" cols="20"><?php echo $desc; ?></textarea> </p> <?php } // Sanitize and return the safe form values public function update( $new_instance, $old_instance ) { $instance = array(); $instance['title'] = ( !empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : ''; $instance['cat_name'] = ( !empty( $new_instance['cat_name'] ) ) ? strip_tags( $new_instance['cat_name'] ) : ''; $instance['cat_age'] = ( !empty( $new_instance['cat_age'] ) ) ? strip_tags( $new_instance['cat_age'] ) : ''; $instance['fav_toy'] = ( !empty( $new_instance['fav_toy'] ) ) ? strip_tags( $new_instance['fav_toy'] ) : ''; if ( current_user_can('unfiltered_html') ) { $instance['description'] = $new_instance['description']; } else { $instance['description'] = stripslashes( wp_filter_post_kses( addslashes($new_instance['description']) ) ); } return $instance; } } // Register widget add_action( 'widgets_init', function(){ register_widget( 'My_Adv_Cat_Widget' ); }); ?>
In the back-end, this is what my widget looks like in the list of available widgets to choose from:
After I have placed it in a widgetized area and filled it out, here is what the form looks like:
What kinds of widgets will you make? Leave your comments down below!