admin管理员组

文章数量:1330597

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,
} = wpponents;
const { compose } = wppose;
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 } = wppose;

/**
 * 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 );

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,
} = wpponents;
const { compose } = wppose;
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 } = wppose;

/**
 * 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 );
Share Improve this question edited Jul 11, 2020 at 14:00 leemon asked Jul 11, 2020 at 11:06 leemonleemon 2,0324 gold badges25 silver badges51 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

In your GalleryImage

const { withSelect } = wp.data;
const { compose } = wppose;

// You should define __
const { __ } = wp.i18n;

In your FeaturedGallery

  • You need to return the element, and set a key for the element (which is a list item): ( I also removed the index because 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() because forEach() 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 return line:

    { 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
    

本文标签: javascriptBuilding a Featured Gallery component for Gutenberg