Skip to content

Instantly share code, notes, and snippets.

@mariovalney
Last active July 11, 2021 18:34
Show Gist options
  • Save mariovalney/b693754b02977a72acf744b64a0bb387 to your computer and use it in GitHub Desktop.
Save mariovalney/b693754b02977a72acf744b64a0bb387 to your computer and use it in GitHub Desktop.
WordPress - Gutenberg Image Selector Component
import { __ } from '@wordpress/i18n';
import { registerBlockType } from '@wordpress/blocks';
import { InnerBlocks, InspectorControls, useBlockProps } from '@wordpress/block-editor';
import { PanelBody } from '@wordpress/components';
import { withSelect } from '@wordpress/data';
import ImageSelector from './image-selector';
registerBlockType( 'mariovalney/image-selector-example', {
apiVersion: 2,
title: __('Image Selector Example'),
icon: 'align-right',
category: 'design',
example: {},
attributes: {
imageId: {
type: 'number',
default: 0,
},
imageUrl: {
type: 'string',
},
},
edit: withSelect( ( select, props ) => {
const { getMedia } = select( 'core' );
if ( props.attributes.imageId ) {
const image = getMedia( props.attributes.imageId );
if (image && image.source_url) {
props.attributes.imageUrl = image.source_url;
}
}
return props;
} )( ( { attributes, setAttributes } ) => {
const onChangeCoverImage = ( image ) => {
setAttributes( {
imageId: image ? ( image.id || 0 ) : 0,
imageUrl: image ? ( image.url || '' ) : ''
} );
};
return (
<div { ...useBlockProps() }>
<InspectorControls>
<PanelBody title={ __( 'Image' ) }>
<ImageSelector
label={ __('Choose a new cover') }
selected={ attributes.imageId }
fallbackUrl={ attributes.imageUrl }
onSelect={ onChangeCoverImage }
/>
</PanelBody>
</InspectorControls>
<div>
<InnerBlocks />
</div>
</div>
);
}
),
save( { attributes } ) {
const blockProps = useBlockProps.save();
// Use attributes.imageUrl as your need.
// In my case, created a backgroundImage with it.
return (
<div { ...blockProps }>
<InnerBlocks.Content />
</div>
);
},
} );
import { __ } from '@wordpress/i18n';
import { Button, ResponsiveWrapper, Spinner } from '@wordpress/components';
import { compose } from '@wordpress/compose';
import { withSelect } from '@wordpress/data';
import { Component } from '@wordpress/element';
import { MediaUpload, MediaUploadCheck } from '@wordpress/block-editor';
class ImageSelector extends Component {
render() {
const permission_fallback = <p>{ __('You need permission to upload images.') }</p>;
const { onSelect, image, fallbackUrl, label } = this.props;
const imageId = image ? image.id : null;
const preview = ( image ? image.source_url : '' ) || fallbackUrl;
return (
<div className="image-selector-control">
<MediaUploadCheck className="main-uploader" fallback={ permission_fallback }>
<MediaUpload
allowedTypes={ [ 'image' ] }
onSelect={ image => onSelect( image ) }
value={ imageId }
render={ ( { open } ) => (
<Button className={ ! preview ? 'image-toggle' : 'image-preview' } onClick={ open } title={ label ? label : 'Click to choose a image.' }>
{ ! preview && ( label || 'Image' ) }
{ !! imageId && ! image && <Spinner /> }
{ !! preview &&
<div className="image-preview-wrapper">
<img src={ preview } />
</div>
}
</Button>
) }
/>
</MediaUploadCheck>
<div className="secondary-buttons">
<MediaUploadCheck>
{ !! preview &&
<Button isLink isDestructive
className="remove-image-link"
onClick={ image => onSelect( null ) }
>
{ __('Remove') }
</Button>
}
</MediaUploadCheck>
</div>
</div>
);
}
}
export default compose(
withSelect( ( select, props ) => {
const { getMedia } = select( 'core' );
let { selected, fallbackUrl } = props;
return {
image: selected && selected.id ? getMedia( selected.id ) : selected,
fallbackUrl: fallbackUrl || '',
};
} ),
)( ImageSelector );
.components-panel,
.editor-styles-wrapper {
.image-selector-control {
margin-bottom: 20px;
.description {
display: block;
font-size: 12px;
}
.image-toggle {
display: block;
width: 100%;
padding: 0;
transition: all 0.1s ease-out;
border: 1px dashed #a2aab2;
background-color: #edeff0;
min-height: 90px;
line-height: 20px;
padding: 8px 0;
text-align: center;
outline: none;
&:hover {
color: inherit;
}
}
.image-preview {
display: block;
width: 100%;
height: 200px;
padding: 0;
transition: all 0.1s ease-out;
border: 1px dashed #a2aab2;
padding: 10px;
}
.image-preview-wrapper {
height: 100%;
width: 100%;
text-align: center;
padding: 1px;
img {
height: 100%;
width: auto;
}
}
.secondary-buttons {
text-align: center;
display: block;
padding: 5px 0 0;
line-height: 1.2;
}
}
}
@mariovalney
Copy link
Author

I created this a long time ago, so I don't remember but it's pretty probably I learned from here:

https://www.liip.ch/en/blog/add-an-image-selector-to-a-gutenberg-block
https://github.com/liip/image-selector-example-wp-plugin

Note: we use imageUrl and fallbackUrl because a imagem can be removed from library or you can add a theme image in your block patterns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment