How to Upload Multiple Images with <MediaUpload>

Now so long ago I published a tutorial about creating a custom image control component for plugin sidebars. The very first question in the comments was “How to select multiple files”?

So let’s dive into it now.

First things first let me show you what we are going to create here.

select multiple images in Gutenberg sidebars

This feature is also a part of my plugin and once the plugin is installed on your website, you can easily create a gallery in Gutenberg sidebars with a small PHP snippet below.

add_filter( 'simple_register_sidebars', function( $sidebars ) {

	$sidebars[] = array(
		'id' => 'misha-test',
		'post_type' => 'page',
		'name' => 'Misha Test',
		'icon' => 'format-gallery',
		'fields' => array(
			array(
				'id' => 'my_gallery',
				'label' => 'Gallery',
				'type' => 'gallery',
			)
		)
	);

	return $sidebars;

} );

But now let’s do it without any plugins step by step.

I recommend to begin with registering meta for our custom field. In order to do so we have to use register_meta() function. I recommend to store an array of image IDs as a meta value, which means that we have to provide the following parameters into the function.

register_meta(
	'post', 
	'misha_gallery', 
	array(
		'type' => 'array',
		'single' => true,
		'show_in_rest' => array(
			'schema' => array( 
				'type'  => 'array', 
				'items' => array( 
					'type' => 'integer' 
				)
			)
		)
	)
)

A little bit more explanation of show_in_rest and schema you can find here.

And the component itself:

const { Button, BaseControl } = window.wp.components
const { MediaUpload, MediaUploadCheck } = window.wp.blockEditor
const { useSelect, useDispatch } = window.wp.data

const RudrGalleryControl = ( props ) => {

	const { imageIds, images } = useSelect( select => {

		const ids = select( 'core/editor' ).getEditedPostAttribute( 'meta' )[ props.metaKey ];
		const images = [];
		
		ids.forEach( ( id ) => {
			const img = select( 'core' ).getMedia( id )
			if( img ) {
				images.push( img )
			}
		} );

		return {
			imageIds: ids,
			images: images,
		}
	})

	const { editPost } = useDispatch( 'core/editor', [ imageIds ] )

	return(
		<BaseControl label={ props.label }>
			<MediaUploadCheck>
				<MediaUpload
					onSelect={ ( media ) =>
						editPost( { meta: { [props.metaKey]: media.map(({ id }) => id ) } } )
					}
					allowedTypes={ [ 'image' ] }
					multiple="add"
					value={ imageIds }
					render={ ( { open } ) => (
						<div>
							{ !! images && images.length > 0 &&
								images.map( image => <img src={ image.source_url } /> )
							}
							<Button variant="secondary" onClick={ open }>Add images</Button>
						</div>

					) }
				/>
			</MediaUploadCheck>
		</BaseControl>
	)
}

export default RudrGalleryControl

Some notes:

<RudrGalleryControl 
	metaKey="misha_gallery" 
	label="Gallery"
/>
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 X