WP List Table Tutorial – Add Bulk Action To List

We create wordpress admin tables using WP_List_Table class to show data. In this tutorial we will see how to add bulk action to WordPress admin table.

Bulk action to wordpress admin table which provide you the option to perform any action to specific data row or into a bulk rows of a list. This is also a bit logical implementation you need to focus on.

Here is an example image. Probably while working with wordpress admin tables of Post, Pages, Users, etc you may or may not seen this bulk action dropdown.

We can select all rows by checking checkboxes and perform action in bulk.

Add Bulk Action To List

Here is the code to add a bulk action to list table.

// To show bulk action dropdown
function get_bulk_actions()
{
        $actions = array(
                'delete_all'    => 'Delete',
                'draft_all' => "Move to Draft"
        );
        return $actions;
}

This code will add a bulk action dropdown with two actions and a apply button.

Function name should be get_bulk_actions(), this is defined function provided by WP_List_Table class.

Inside $actions array, these are actions like Delete, Move to Draft, etc. delete_all, draft_all are keys which will be used to pass in query string.

To perform actions, we need to create handlers. WP_List_Table class doesn’t provide the handler for bulk action.

Define form Tag

We need to wrap our admin table into a form. Which means when we select bulk action and click on Apply button then the form will be submitted.

<form method="get">
    <input type="hidden" name="page" value="employees_list_table" />
    <?php
    $empTable->search_box('search', 'search_id');

    // Display table
    $empTable->display();
    ?>
</form>

method type of this form is “get”. When we submit this form then many other parameters will be attached inside query string. On the basis of query string parameters we will create handler for bulk action.

While doing bulk operation we need to check either specific data row or we can select all data rows at once. For adding checkbox with each data row of List table,

Add Checkbox to each Row

// To show checkbox with each row
function column_cb($item)
{
        return sprintf(
                '<input type="checkbox" name="user[]" value="%s" />',
                $item['ID']
        );
}

$item[‘ID’] is the ID value for each row. When we submit after selecting checkboxes then we can access all selected checkboxes by user name attribute.

Bulk Action Handler

To handle bulk operation we need to define code for it. Either we can create a separate method to handle. But here I will create inside prepare_items() method.

// bulk action
if (isset($_GET['action']) && $_GET['page'] == "employees_list_table" && $_GET['action'] == "delete_all") {
        $empIDs = $_GET['user'];
        
        //... do operation
}

if (isset($_GET['action']) && $_GET['page'] == "employees_list_table" && $_GET['action'] == "draft_all") {
        $empIDs = $_GET['user'];
        
        //... do operation
}

Plugin Setup

Here, is the complete code of plugin.

<?php
/*
Plugin Name:  Simple Employees Table
Description: It displays a table with employee data
Author: Online Web Tutor
Author URI: https://onlinewebtutorblog.com/
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: basic-wp-list-table
Version: 1.0
*/

// Loading table class
if (!class_exists('WP_List_Table')) {
      require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
}

// Extending class
class Employees_List_Table extends WP_List_Table
{
      private $users_data;

      private function get_users_data($search = "")
      {
            global $wpdb;

            if (!empty($search)) {
                  return $wpdb->get_results(
                        "SELECT ID,user_login,user_email,display_name from {$wpdb->prefix}users WHERE ID Like '%{$search}%' OR user_login Like '%{$search}%' OR user_email Like '%{$search}%' OR display_name Like '%{$search}%'",
                        ARRAY_A
                  );
            } else {
                  return $wpdb->get_results(
                        "SELECT ID,user_login,user_email,display_name from {$wpdb->prefix}users",
                        ARRAY_A
                  );
            }
      }

      // Define table columns
      function get_columns()
      {
            $columns = array(
                  'cb'            => '<input type="checkbox" />',
                  'ID' => 'ID',
                  'user_login' => 'Username',
                  'display_name'    => 'Name',
                  'user_email'      => 'Email'
            );
            return $columns;
      }

      // Bind table with columns, data and all
      function prepare_items()
      {
            if (isset($_GET['page']) && isset($_GET['s'])) {
                  $this->users_data = $this->get_users_data($_GET['s']);
            } else {
                  $this->users_data = $this->get_users_data();
            }

            $columns = $this->get_columns();
            $hidden = array();
            $sortable = $this->get_sortable_columns();
            $this->_column_headers = array($columns, $hidden, $sortable);

            /* pagination */
            $per_page = $this->get_items_per_page('employees_per_page', 2);
            $current_page = $this->get_pagenum();
            $total_items = count($this->users_data);

            // edit
            if (isset($_GET['action']) && $_GET['page'] == "employees_list_table" && $_GET['action'] == "edit") {
                  $empID = intval($_GET['employee']);

                  //... do operation
            }

            // delete
            if (isset($_GET['action']) && $_GET['page'] == "employees_list_table" && $_GET['action'] == "delete") {
                  $empID = intval($_GET['employee']);

                  //... do operation
            }

            // bulk action
            if (isset($_GET['action']) && $_GET['page'] == "employees_list_table" && $_GET['action'] == "delete_all") {
                  $empIDs = $_GET['user'];
                  
                  //... do operation
            }

            if (isset($_GET['action']) && $_GET['page'] == "employees_list_table" && $_GET['action'] == "draft_all") {
                  $empIDs = $_GET['user'];
                  
                  //... do operation
            }

            $this->users_data = array_slice($this->users_data, (($current_page - 1) * $per_page), $per_page);

            $this->set_pagination_args(array(
                  'total_items' => $total_items, // total number of items
                  'per_page'    => $per_page // items to show on a page
            ));

            usort($this->users_data, array(&$this, 'usort_reorder'));

            $this->items = $this->users_data;
      }

      // bind data with column
      function column_default($item, $column_name)
      {
            switch ($column_name) {
                  case 'ID':
                  case 'user_login':
                  case 'user_email':
                        return $item[$column_name];
                  case 'display_name':
                        return ucwords($item[$column_name]);
                  default:
                        return print_r($item, true); //Show the whole array for troubleshooting purposes
            }
      }

      // To show checkbox with each row
      function column_cb($item)
      {
            return sprintf(
                  '<input type="checkbox" name="user[]" value="%s" />',
                  $item['ID']
            );
      }

      // Add sorting to columns
      protected function get_sortable_columns()
      {
            $sortable_columns = array(
                  'user_login'  => array('user_login', false),
                  'display_name' => array('display_name', false),
                  'user_email'   => array('user_email', true)
            );
            return $sortable_columns;
      }

      // Sorting function
      function usort_reorder($a, $b)
      {
            // If no sort, default to user_login
            $orderby = (!empty($_GET['orderby'])) ? $_GET['orderby'] : 'user_login';
            // If no order, default to asc
            $order = (!empty($_GET['order'])) ? $_GET['order'] : 'asc';
            // Determine sort order
            $result = strcmp($a[$orderby], $b[$orderby]);
            // Send final sort direction to usort
            return ($order === 'asc') ? $result : -$result;
      }

      // Adding action buttons to column
      function column_user_login($item)
      {
            $actions = array(
                  'edit'      => sprintf('<a href="?page=%s&action=%s&employee=%s">Edit</a>', $_REQUEST['page'], 'edit', $item['ID']),
                  'delete'    => sprintf('<a href="?page=%s&action=%s&employee=%s">Delete</a>', $_REQUEST['page'], 'delete', $item['ID']),
            );

            return sprintf('%1$s %2$s', $item['user_login'], $this->row_actions($actions));
      }

      // To show bulk action dropdown
      function get_bulk_actions()
      {
            $actions = array(
                  'delete_all'    => 'Delete',
                  'draft_all' => "Move to Draft"
            );
            return $actions;
      }
}

// Adding menu
function my_add_menu_items()
{
      $hook = add_menu_page('Employees List Table', 'Employees List Table', 'activate_plugins', 'employees_list_table', 'employees_list_init');

      // screen option
      add_action("load-$hook", 'my_tbl_add_options');

      function my_tbl_add_options()
      {
            $option = 'per_page';

            $args = array(
                  'label' => 'Employees',
                  'default' => 2,
                  'option' => 'employees_per_page'
            );
            add_screen_option($option, $args);

            $empTable = new Employees_List_Table();
      }
}
add_action('admin_menu', 'my_add_menu_items');

// get saved screen meta value
add_filter('set-screen-option', 'my_table_set_option', 10, 3);

function my_table_set_option($status, $option, $value)
{
      return $value;
}

// Plugin menu callback function
function employees_list_init()
{
      // Creating an instance
      $empTable = new Employees_List_Table();

      echo '<style>#the-list .row-actions{left:0;}</style><div class="wrap"><h2>Employees List Table</h2>';
      // Prepare table
      $empTable->prepare_items();
?>
      <form method="get">
            <input type="hidden" name="page" value="employees_list_table" />
            <?php
            $empTable->search_box('search', 'search_id');

            // Display table
            $empTable->display();
            ?>
      </form>
<?php
      echo '</div>';
}

Plugin

Go to Plugins >> Installed Plugins

Click on Activate

It will create a admin menu. When we click on it.

Now, successfully we have implemented the bulk action to wordpress admin table.

Sanjay KumarHello friends, I am Sanjay Kumar a Web Developer by profession. Additionally I'm also a Blogger, Youtuber by Passion. I founded Online Web Tutor and Skillshike platforms. By using these platforms I am sharing the valuable knowledge of Programming, Tips and Tricks, Programming Standards and more what I have with you all. Read more