Bulk Edit in 2 Steps

Here is bulk edit with custom inputs in action:

Add two bulk quick edit inputs - text field and checkbox.
Complete the quick edit tutorial first, then follow the below steps if you want to implement the same functionality.

Step 1. Use bulk_edit_custom_box to make the fields appear in bulk edit

Actually to continue with bulk edit, you have to implement the whole quick edit tutorial before. Surprise!😂 You can find ready misha_quick_edit_fields() function in Step 2 of that tutorial.

add_action('bulk_edit_custom_box',  'misha_quick_edit_fields', 10, 2);

Once the fields are appeared, you can continue to the next step.

Step 2. Save Bulk Edit fields

I was full of hope to find the appropriate bulk_save_post hook or something like that inside the WordPress core, but I didn’t find anything…

Everywhere in the other tutorials and even in the official WordPress codex it is recommended to save the bulk edit field values with AJAX, the way I described below. I hope I will find a better way to do that later and I will update my tutorial.

But now add this jQuery code at the end of populate.js file which we created and enqueued in admin area in Step 4 of the quick edit tutorial.

	$( 'body' ).on( 'click', 'input[name="bulk_edit"]', function() {

		// let's add the WordPress default spinner just before the button
		$( this ).after('<span class="spinner is-active"></span>');

		// define: prices, featured products and the bulk edit table row
		var bulk_edit_row = $( 'tr#bulk-edit' ),
		    post_ids = new Array()
		    price = bulk_edit_row.find( 'input[name="price"]' ).val(),
		    featured = bulk_edit_row.find( 'input[name="featured"]' ).attr('checked') ? 1 : 0;

		// now we have to obtain the post IDs selected for bulk edit
		bulk_edit_row.find( '#bulk-titles' ).children().each( function() {
			post_ids.push( $( this ).attr( 'id' ).replace( /^(ttle)/i, '' ) );

		// save the data with AJAX
			url: ajaxurl, // WordPress has already defined the AJAX url for us (at least in admin area)
			type: 'POST',
			data: {
				action: 'misha_save_bulk', // wp_ajax action hook
				post_ids: post_ids, // array of post IDs
				price: price, // new price
				featured: featured, // new value for product featured
				nonce: $('#misha_nonce').val() // I take the nonce from hidden #misha_nonce field

This function process our AJAX call, add it to your current theme functions.php file.

add_action( 'wp_ajax_misha_save_bulk', 'misha_save_bulk_edit_hook' ); 
// add_action( 'wp_ajax_{ACTION}', 'FUNCTION NAME' );

function misha_save_bulk_edit_hook() {

	// you can check the same nonce we added in Quick Edit tutorial
	if ( !wp_verify_nonce( $_POST['nonce'], 'quick_edit_misha_nonce' ) ) {

	// well, if post IDs are empty, it is nothing to do here
	if( empty( $_POST[ 'post_ids' ] ) ) {

	// for each post ID
	foreach( $_POST[ 'post_ids' ] as $id ) {

		// if price is empty, maybe we shouldn't change it
		if( !empty( $_POST[ 'price' ] ) ) {
			update_post_meta( $id, 'product_price', $_POST['price'] );

		// another story with checkbox
		if ( !empty( $_POST['featured'] ) ) {
			update_post_meta( $id, 'product_featured', 'on' );
		} else {
			update_post_meta( $id, 'product_featured', '' );



If you have any questions or suggestions to this post, please leave it in comments below.

Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on Twitter