Tag Archives: tutorial

Adding an AJAX Preview to a WordPress Widget Plugin Tutorial

If you would like to add a preview mechanism to your WordPress plugin, you can use WordPress’ Ajax capabilities. This way, you can make changes in the admin area and preview them on the front end without having to save or reload the page.

In this context, I’ll add an AJAX preview to our plugin which will preview the list of posts in a modal window.

The previous post is: https://horkan.com/2023/08/08/creating-a-wordpress-widget-plugin-tutorial

Modify your plugin’s main PHP file (my_posts_widget.php) as follows:

<?php
/**
 * Plugin Name: My Posts Widget
 * Description: A widget that displays a list of all the posts displayed on the current page.
 * Version: 1.0
 * Author: Your Name
 */

// Register and load the widget
function my_posts_widget_load() {
    register_widget( 'my_posts_widget' );
}
add_action( 'widgets_init', 'my_posts_widget_load' );

// Creating the widget 
class my_posts_widget extends WP_Widget {

    function __construct() {
        parent::__construct(
            'my_posts_widget',
            __('My Posts Widget', 'my_posts_widget_domain'),
            array( 'description' => __( 'A widget that displays a list of all the posts displayed on the current page.', 'my_posts_widget_domain' ), ) 
        );
    }

    // Creating widget front-end
    public function widget( $args, $instance ) {
        global $posts;

        $title = apply_filters( 'widget_title', $instance['title'] );
        
        echo $args['before_widget'];
        if ( ! empty( $title ) )
            echo $args['before_title'] . $title . $args['after_title'];
        
        // this is where we output the posts
        echo '<ul>';
        foreach ($posts as $post) {
            echo '<li><a href="' . get_permalink($post) . '">' . $post->post_title . '</a></li>';
        }
        echo '</ul>';
        echo $args['after_widget'];
    }

    // Widget Backend 
    public function form( $instance ) {
        if ( isset( $instance[ 'title' ] ) ) {
            $title = $instance[ 'title' ];
        }
        else {
            $title = __( 'New title', 'my_posts_widget_domain' );
        }
        // Widget admin form
        ?>
        <p>
        <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( '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>
        <?php 

// Add a Preview button
        ?>
        <p>
            <button id="my-posts-widget-preview-btn" class="button">Preview</button>
            <div id="my-posts-widget-preview"></div>
        </p>
        <?php
    }

    // Updating widget replacing old instances with new
    public function update( $new_instance, $old_instance ) {
        $instance = array();
        $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
        return $instance;
    }
}

add_action( 'admin_footer', 'my_posts_widget_preview_script' );
function my_posts_widget_preview_script() {
    ?>
    <script type="text/javascript" >
    jQuery(document).ready(function($) {
        $('#my-posts-widget-preview-btn').on('click', function(e) {
            e.preventDefault();

            $.ajax({
                url: ajaxurl, // default WP ajax url
                data: {
                    'action': 'my_posts_widget_preview',
                },
                success:function(response) {
                    // Add response in Modal window
                    $('#my-posts-widget-preview').html(response);
                    // You can use any modal plugin or write your own code to display this response in modal
                },
                error: function(error){
                    console.log(error);
                }
            });  

        });
    });
    </script>
    <?php
}

add_action( 'wp_ajax_my_posts_widget_preview', 'my_posts_widget_preview' );
function my_posts_widget_preview() {
    global $posts;

    // Start capturing output
    ob_start();
    
    echo '<ul>';
    foreach ($posts as $post) {
        echo '<li><a href="' . get_permalink($post) . '">' . $post->post_title . '</a></li>';
    }
    echo '</ul>';
    
    // Get current buffer contents and delete current output buffer
    $output = ob_get_clean();

    echo $output;
    
    wp_die(); // All ajax handlers should die when finished
}

The above modification does the following:

  • Adds a Preview button in the widget form that, when clicked, makes an AJAX call to the server.
  • The AJAX call invokes a server-side PHP function (my_posts_widget_preview()) that generates a list of posts and sends it back as the AJAX response.
  • The AJAX response is then inserted into a div for preview.

Please note that for this code to work, AJAX should be properly set up in your WordPress and the admin user should have the right permissions to view the posts.

Remember, this is a very basic preview mechanism and may not reflect exactly how the widget will look on the frontend of your site. Depending on your theme and the styles it applies to widgets, the actual appearance may be different.

You might want to add more advanced features, like a live preview that updates automatically when you change the widget’s settings, or a more accurate representation of the frontend styles. This will require more complex code and a good understanding of both PHP and JavaScript.

Creating a WordPress Widget Plugin Tutorial

I wanted a widget that displays a list of all the posts displayed on the current page, but I couldn’t find a WordPress widget plugin that would do what I wanted. Ergo sum I’ll build it myself. Here’s a super short tutorial on how to create a WordPress widget plugin.

To accomplish this, we’ll create a plugin that registers a widget. This widget will grab the global $posts object from WordPress (which contains the posts that are being displayed on the current page), and list their titles in a widget.

Here’s my template code:

<?php
/**
 * Plugin Name: My Posts Widget
 * Description: A widget that displays a list of all the posts displayed on the current page.
 * Version: 1.0
 * Author: Your Name
 */

// Register and load the widget
function my_posts_widget_load() {
    register_widget( 'my_posts_widget' );
}
add_action( 'widgets_init', 'my_posts_widget_load' );

// Creating the widget 
class my_posts_widget extends WP_Widget {

    function __construct() {
        parent::__construct(
            'my_posts_widget',
            __('My Posts Widget', 'my_posts_widget_domain'),
            array( 'description' => __( 'A widget that displays a list of all the posts displayed on the current page.', 'my_posts_widget_domain' ), ) 
        );
    }

    // Creating widget front-end
    public function widget( $args, $instance ) {
        global $posts;

        $title = apply_filters( 'widget_title', $instance['title'] );
        
        echo $args['before_widget'];
        if ( ! empty( $title ) )
            echo $args['before_title'] . $title . $args['after_title'];
        
        // this is where we output the posts
        echo '<ul>';
        foreach ($posts as $post) {
            echo '<li><a href="' . get_permalink($post) . '">' . $post->post_title . '</a></li>';
        }
        echo '</ul>';
        echo $args['after_widget'];
    }

    // Widget Backend 
    public function form( $instance ) {
        if ( isset( $instance[ 'title' ] ) ) {
            $title = $instance[ 'title' ];
        }
        else {
            $title = __( 'New title', 'my_posts_widget_domain' );
        }
        // Widget admin form
        ?>
        <p>
        <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( '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>
        <?php 
    }

    // Updating widget replacing old instances with new
    public function update( $new_instance, $old_instance ) {
        $instance = array();
        $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
        return $instance;
    }
}

Here’s what’s happening in the code:

  1. We’re creating a new widget with the name “My Posts Widget”. This will appear in the list of available widgets in the WordPress admin dashboard.
  2. The widget has a title which is editable from the widget settings.
  3. In the widget method, we’re accessing the global $posts variable, which WordPress sets with all the posts being displayed on the current page.
  4. We’re then iterating through each of the posts and adding a link to the post in an unordered list.

To install this plugin, you need to:

  1. Create a my-posts-widget directory. The majority of plugins follow the same pattern re: use of “-” to separate words.
  2. Copy the code above and put it in my_posts_widget.php file inside my-posts-widget directory.
  3. Compress the my-posts-widget directory to my-posts-widget.zip.
  4. Go to your WordPress admin dashboard, then go to “Plugins > Add New > Upload Plugin”.
  5. Choose the my-posts-widget.zip file and click “Install Now”.
  6. After installation, activate the plugin by clicking “Activate”.

After you’ve done this, you’ll see a new widget available in your list of widgets called “My Posts Widget”. You can add it to any widget area in your theme like you would with any other widget.

Please note that this plugin will display all posts that are being displayed on the current page, regardless of where they’re displayed. That includes posts in main query, posts in sidebars, posts in footer etc. If you need more precise control, you’ll need to modify the code to suit your needs.