I’m building a Featured Gallery component for Gutenberg. As a guide, I’m using the existing Featured Image component from Gutenberg. Basically, instead of storing a single image id, the component stores an array of image ids in a dedicated meta field (of type array) called _featured_gallery.
Apparently, the getting and setting part is working, but I’m unable to show the grid of selected images (the featured-gallery-grid part in the code).
Any ideas? My knowledge of Gutenberg and React is limited, so I’m a bit lost here. Any help would be appreciated.
FeaturedGallery:
/**
* WordPress dependencies
*/
const { __ } = wp.i18n;
const {
BaseControl,
Button,
withNotices,
} = wp.components;
const { compose } = wp.compose;
const { withSelect, withDispatch } = wp.data;
const { MediaUpload, MediaUploadCheck } = wp.blockEditor;
/**
* Internal dependencies
*/
import GalleryImage from './gallery-image';
const ALLOWED_MEDIA_TYPES = [ 'image' ];
function FeaturedGallery( {
currentPostId,
featuredGalleryIds,
onUpdateGallery,
noticeUI,
} ) {
const instructions = (
<p>
{ __(
'To edit the featured gallery, you need permission to upload media.', 'my-featured-gallery'
) }
</p>
);
return (
<BaseControl
className="my-featured-gallery"
>
{ noticeUI }
<div className="editor-post-featured-gallery">
<MediaUploadCheck fallback={ instructions }>
<div className="editor-post-featured-gallery__container">
{ !! featuredGalleryIds && (
<ul className="featured-gallery-grid">
{ featuredGalleryIds.forEach( ( img, index ) => {
<li>
<GalleryImage
id={ img }
/>
</li>
} ) }
</ul>
) }
</div>
<MediaUpload
title={ __( 'Featured gallery', 'my-featured-gallery' ) }
multiple
onSelect={ onUpdateGallery }
allowedTypes={ ALLOWED_MEDIA_TYPES }
render={ ( { open } ) => (
<Button
onClick={ open }
isSecondary
>
{
__( 'Add gallery images', 'my-featured-gallery' )
}
</Button>
) }
value={ featuredGalleryIds }
/>
</MediaUploadCheck>
</div>
</BaseControl>
);
}
const applyWithSelect = withSelect( ( select ) => {
const { getPostType } = select( 'core' );
const { getCurrentPostId, getEditedPostAttribute } = select(
'core/editor'
);
const meta = getEditedPostAttribute( 'meta' );
const featuredGalleryIds = meta._featured_gallery;
return {
currentPostId: getCurrentPostId(),
postType: getPostType( getEditedPostAttribute( 'type' ) ),
featuredGalleryIds,
};
} );
const applyWithDispatch = withDispatch( ( dispatch ) => {
const { editPost } = dispatch( 'core/editor' );
return {
onUpdateGallery( images ) {
const items = images.map( ( item ) => item['id'] );
const meta = { _featured_gallery: items };
editPost( { meta } );
},
};
}
);
export default compose(
withNotices,
applyWithSelect,
applyWithDispatch,
)( FeaturedGallery );
GalleryImage:
/**
* WordPress dependencies
*/
const { withSelect } = wp.data;
const { compose } = wp.compose;
/**
* Internal dependencies
*/
function GalleryImage( {
id,
image
} ) {
return (
<figure>
{ image && ( <div className="img-container">
<img
src={ image.media_details.sizes.thumbnail.source_url }
width={ image.media_details.sizes.thumbnail.width }
height={ image.media_details.sizes.thumbnail.height }
alt={ __( 'Thumbnail of the image.', 'my-featured-gallery' ) }
style={ {
display: 'block',
marginBottom: '8px',
} }
/>
</div> ) }
</figure>
);
}
const applyWithSelect = withSelect( ( select, ownProps ) => {
const { getMedia } = select( 'core' );
const { id } = ownProps;
return {
image: id ? getMedia( parseInt( id, 10 ) ) : null,
};
} );
export default compose( [
applyWithSelect
] )( GalleryImage );
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
In your GalleryImage
const { withSelect } = wp.data;
const { compose } = wp.compose;
// You should define __
const { __ } = wp.i18n;
In your FeaturedGallery
-
You need to
returnthe element, and set akeyfor the element (which is a list item): ( I also removed theindexbecause it’s not being used.. if we define a variable, it should be used. 🙂 )And because an element should be returned, then you should use
map()becauseforEach()doesn’t return anything and only applies a function to each element in the array.{ featuredGalleryIds.map( ( img ) => { return ( <li key={ img }> <GalleryImage id={ img } /> </li> ); } ) }Alternate/simpler version — this is basically same as above, but you’d use the above if you want to perform some logic before the
returnline:{ featuredGalleryIds.map( ( img ) => ( <li key={ img }> <GalleryImage id={ img } /> </li> ) ) } -
Then (not a major issue, but) in the
applyWithDispatch(), you should use the dot notation (item.id) and not the array notation (item['id']).const items = images.map( ( item ) => item.id ); // like this const items = images.map( ( item ) => item['id'] ); // not this
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0