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

I develop websites since 2008, so it is total of 13 years of experience, oh my gosh. Most of all I love love love to create websites with WordPress and Gutenberg, some ideas and thoughts I share throughout my blog.

Need some developer help? Contact me