0

I created a custom block. It works but not able to get the block preview image working. Is there anything else I need to do? I am using create-guten-block to create the block.

Can anyone please help?

/**
 * BLOCK: bbr
 *
 * Registering a basic block with Gutenberg.
 * Simple block, renders and saves the same content without any interactivity.
 */

//  Import CSS.
import './editor.scss';


const { __ } = wp.i18n; // Import __() from wp.i18n
const {
    registerBlockType} = wp.blocks; // Import registerBlockType() from wp.blocks
const {  RichText, InspectorControls, InnerBlocks }=wp.blockEditor;
const {
    SelectControl,
} = wp.components;

/**
 * Register: aa Gutenberg Block.
 *
 * Registers a new block provided a unique name and an object defining its
 * behavior. Once registered, the block is made editor as an option to any
 * editor interface where blocks are implemented.
 *
 * @link https://wordpress.org/gutenberg/handbook/block-api/
 * @param  {string}   name     Block name.
 * @param  {Object}   settings Block settings.
 * @return {?WPBlock}          The block, if it has been successfully
 *                             registered; otherwise `undefined`.
 */
 import './editor.scss';
registerBlockType( 'bbr/block-card', {
    // Block name. Block names must be string that contains a namespace prefix. Example: my-plugin/my-custom-block.
    title: __( 'Card' ), // Block title.
    description: __('Card Block', 'bbr/block-cta'),
    icon: 'align-center', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/.
    category: 'bbr-blocks', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed.
    keywords: [
        __( 'card ' ),
        __( 'card block' ),
        __( 'bbr' ),
    ],
    attributes: {
        heading: {
            type: 'core/heading',
            default: 'Your heading'
        },
        subheading: {
            type: 'core/heading',
            default: 'Sub heading'
        },
        paraText: {
            type: 'string',
            default: "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. "
        },
        buttonText: {
            type: 'string',
            default: ''
        },
        buttonLink: {
            type: 'string',
            default: ''
        },
        buttonClass: {
            type: 'string',
            default: 'btn btn-primary'
        },
        GridClass: {
            type: 'string',
            default: 'col-md-3'
        },
        selectMdColumns: {
            type: 'string',
            default: ''
        },
        selectSmColumns: {
            type: 'string',
            default: ''
        },
        selectXsColumns: {
            type: 'string',
            default: ''
        },
        selectLgColumns: {
            type: 'string',
            default: ''
        },
       

  },
  example: {
    attributes: {
        cover: 'img/test.jpg',
    },
    viewportWidth: 800
},


    /**
     * The edit function describes the structure of your block in the context of the editor.
     * This represents what the editor will render when the block is used.
     *
     * The "edit" property must be a valid function.
     *
     * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
     *
     * @param {Object} props Props.
     * @returns {Mixed} JSX Component.
     */
    edit: ( props ) => {
        
       
        const onChangeheading = value => {  
            props.setAttributes({ heading: value })
        };

        const onChangesubheading = value => {   
            props.setAttributes({ subheading: value })
        };
        const onChangeparaText = value => { 
            props.setAttributes({ paraText: value })
        };
        const onChangebuttonText = value => {   
            props.setAttributes({ buttonText: value })
        };
        const onChangebuttonLink = value => {   
            props.setAttributes({ buttonLink: value })
        };
        function onChangebuttonClass( newValue ) {
            props.setAttributes( { buttonClass: newValue } );
        };
        function onChangeselectLgColumns( newValue ) {
            props.setAttributes( { selectLgColumns: newValue } );
        }
        function onChangeselectMdColumns( newValue ) {
            props.setAttributes( { selectMdColumns: newValue } );
        }
        function onChangeselectSmColumns( newValue ) {
            props.setAttributes( { selectSmColumns: newValue } );
        }
        function onChangeselectXsColumns( newValue ) {
            props.setAttributes( { selectXsColumns: newValue } );
        }
        
        const MY_TEMPLATE = [
            [ 'core/image' ],   
        ];

        return [(
            
            <div class="card">
                <div class="card-body">
                
                    <InnerBlocks
                            template={ MY_TEMPLATE }
                            templateLock="all"
                        />  
                    <RichText
                        tagName="h5"
                        placeholder="Edit heading "
                        className="card-title"
                        focus = {focus}
                        value={ props.attributes.heading }
                        onChange={ onChangeheading }
                        keepPlaceholderOnFocus= {true}
                    />
                    
                    <RichText
                        tagName="h6"
                        placeholder="Sub heading "
                        className="card-subtitle mb-2 text-muted"
                        focus = {focus}
                        value={ props.attributes.subheading }
                        onChange={ onChangesubheading }
                        keepPlaceholderOnFocus= {true}
                    />
                    
                    <RichText
                        tagName="p"
                        placeholder="Paragraph text"
                        className= 'card-text'
                        focus = {focus}
                        value={ props.attributes.paraText }
                        onChange={ onChangeparaText }
                        keepPlaceholderOnFocus= {true}
                    />
                    <RichText
                        tagName="a"
                        placeholder="Button text"
                        focus = {focus}
                        className= { props.attributes.buttonClass }
                        value={ props.attributes.buttonText }
                        onChange={ onChangebuttonText }
                        keepPlaceholderOnFocus= {true}
                    />
                    <RichText
                        placeholder="http://"
                        className= 'card-text'
                        focus = {focus}
                        value={ props.attributes.buttonLink }
                        onChange={ onChangebuttonLink }
                        keepPlaceholderOnFocus= {true}
                    />
                    
                </div>
            </div>
            
        ),(
            <InspectorControls>
                
                <SelectControl
                    label="Select button class"
                    value={ buttonClass }
                    options={
                        [
                            { value: '', label: 'Select' },
                            { value: 'btn btn-primary', label: 'primary' },
                            { value: 'btn btn-secondary', label: 'secondary' },
                            { value: 'btn btn-success', label: 'success' },
                            { value: 'btn btn-danger', label: 'danger' },
                            { value: 'btn btn-warning', label: 'warning' },
                            { value: 'btn btn-info', label: 'info' },
                            { value: 'btn btn-light', label: 'light' },
                            { value: 'btn btn-dark', label: 'dark' },
                            { value: 'btn btn-link', label: 'link' },

                        ]
                    }
                    onChange={ onChangebuttonClass }
                />
                 <SelectControl
                            label="Select column width for lg devices"
                            value={ selectLgColumns }
                            options={
                                [
                                    { value: '', label: 'None' },
                                    { value: 'col-lg-1', label: 'col-lg-1' },
                                    { value: 'col-lg-2', label: 'col-lg-2' },
                                    { value: 'col-lg-3', label: 'col-lg-3' },
                                    { value: 'col-lg-4', label: 'col-lg-4' },
                                    { value: 'col-lg-5', label: 'col-lg-5' },
                                    { value: 'col-lg-6', label: 'col-lg-6' },
                                    { value: 'col-lg-7', label: 'col-lg-7' },
                                    { value: 'col-lg-8', label: 'col-lg-8' },
                                    { value: 'col-lg-9', label: 'col-lg-9' },
                                    { value: 'col-lg-10', label: 'col-lg-10' },
                                    { value: 'col-lg-11', label: 'col-lg-11' },
                                    { value: 'col-lg-12', label: 'col-lg-12' },

                                ]
                            }
                            onChange={ onChangeselectLgColumns }
                        />

                        <SelectControl
                            label="Select column width for md devices"
                            value={ selectMdColumns }
                            options={
                                [
                                    { value: '', label: 'None' },
                                    { value: 'col-md-1', label: 'col-md-1' },
                                    { value: 'col-md-2', label: 'col-md-2' },
                                    { value: 'col-md-3', label: 'col-md-3' },
                                    { value: 'col-md-4', label: 'col-md-4' },
                                    { value: 'col-md-5', label: 'col-md-5' },
                                    { value: 'col-md-6', label: 'col-md-6' },
                                    { value: 'col-md-7', label: 'col-md-7' },
                                    { value: 'col-md-8', label: 'col-md-8' },
                                    { value: 'col-md-9', label: 'col-md-9' },
                                    { value: 'col-md-10', label: 'col-md-10' },
                                    { value: 'col-md-11', label: 'col-md-11' },
                                    { value: 'col-md-12', label: 'col-md-12' },

                                ]
                            }
                            onChange={ onChangeselectMdColumns }
                        />
                        <SelectControl
                            label="Select column width for sm devices"
                            value={ selectSmColumns }
                            options={
                                [
                                    { value: '', label: 'None' },
                                    { value: 'col-sm-1', label: 'col-sm-1' },
                                    { value: 'col-sm-2', label: 'col-sm-2' },
                                    { value: 'col-sm-3', label: 'col-sm-3' },
                                    { value: 'col-sm-4', label: 'col-sm-4' },
                                    { value: 'col-sm-5', label: 'col-sm-5' },
                                    { value: 'col-sm-6', label: 'col-sm-6' },
                                    { value: 'col-sm-7', label: 'col-sm-7' },
                                    { value: 'col-sm-8', label: 'col-sm-8' },
                                    { value: 'col-sm-9', label: 'col-sm-9' },
                                    { value: 'col-sm-10', label: 'col-sm-10' },
                                    { value: 'col-sm-11', label: 'col-sm-11' },
                                    { value: 'col-sm-12', label: 'col-sm-12' },

                                ]
                            }
                            onChange={ onChangeselectSmColumns }
                        />
                        <SelectControl
                            label="Select column width for xs devices"
                            value={ selectXsColumns }
                            options={
                                [
                                    { value: '', label: 'None' },
                                    { value: 'col-xs-1', label: 'col-xs-1' },
                                    { value: 'col-xs-2', label: 'col-xs-2' },
                                    { value: 'col-xs-3', label: 'col-xs-3' },
                                    { value: 'col-xs-4', label: 'col-xs-4' },
                                    { value: 'col-xs-5', label: 'col-xs-5' },
                                    { value: 'col-xs-6', label: 'col-xs-6' },
                                    { value: 'col-xs-7', label: 'col-xs-7' },
                                    { value: 'col-xs-8', label: 'col-xs-8' },
                                    { value: 'col-xs-9', label: 'col-xs-9' },
                                    { value: 'col-xs-10', label: 'col-xs-10' },
                                    { value: 'col-xs-11', label: 'col-xs-11' },
                                    { value: 'col-xs-12', label: 'col-xs-12' },

                                ]
                            }
                            onChange={ onChangeselectXsColumns }
                        />
            </InspectorControls>
        )]
    },
 
    save: ( props ) => {
        
        
        return (
            <div className= { (props.attributes.selectSmColumns ) + ' ' + ( props.attributes.selectMdColumns ) + ' ' + ( props.attributes.selectXsColumns ) + ' ' + ( props.attributes.selectLgColumns ) } >
                <div class="card">
                    <div class="card-body">
                        <InnerBlocks.Content />
                        <h5 class="card-title">{ props.attributes.heading  }</h5>
                        <h6 class="card-subtitle mb-2 text-muted">{ props.attributes.subheading  }</h6>
                        <p class="card-text">{ props.attributes.paraText  }</p>
                        <a href={ props.attributes.buttonLink } class={ props.attributes.buttonClass }>{ props.attributes.buttonText }</a>
                    </div>
                </div>
            </div>
        );
    }
    
} );

More Details: (from a comment to a deleted answer)

Getting the block preview is no problem. My card Block is creating the preview. I want to display an image instead of the block preview.

6
  • your code block is showing only the top half of a registerBlockType call, and there are no edit or save components, can you edit your question to fix this? Also you should never store the URLs of images, store their attachment/media IDs instead or you'll run into lots of issues, especially during site migrations or with plugins that optimise or adjust images such as CDNs. There is also broken indenting. If you do not have an edit/save component set then that is why your preview is not working, the block preview is not an image/screenshot, e.g. preview the video block and you'll see a video
    – Tom J Nowell
    Commented Oct 10, 2022 at 14:46
  • @TomJNowell Updated the code. Thanks for looking into it. I really appreciate it. Commented Oct 10, 2022 at 14:54
  • thanks for updating this, note that putting <InnerBlocks.Content /> or <InnerBlocks /> alongside other tags rather than on its own inside another tag can cause block validation issues, you should try to keep it there on its own like this: <div><InnerBlocks.Content /></div> instead of <div><InnerBlocks.Content /><span/></div>
    – Tom J Nowell
    Commented Oct 10, 2022 at 15:03
  • I see now, the image isn't strictly a part of your block but rather it's the core image block as a child
    – Tom J Nowell
    Commented Oct 10, 2022 at 15:04
  • I would like to display the preview of the block. The image is not the part of the block code. I am trying to implement example from developer.wordpress.org/block-editor/reference-guides/block-api/… Commented Oct 10, 2022 at 15:09

1 Answer 1

1

I created a custom block. It works but not able to get the block preview image working.

The cover in the code sample for the example prop was just an example attribute, so setting cover: '<image URL>' does not automatically displays the image when previewing the block via the block inserter.

However, the preview uses your edit function's output, so whatever the function returns will be displayed in the preview panel/area, i.e. the editor will basically call your edit function and pass the attributes in the example prop.

So regarding this:

Getting the block preview is no problem. My card Block is creating the preview. I want to display an image instead of the block preview.

One easy way would be to actually register the cover as an attribute for your block: (I would, however, use the name _cover where the underscore normally indicates something that is private or read-only)

  1. Register the attribute:

    attributes: {
        // your other attributes
    
        cover: {
            type: 'string',
            default: '', // keep it empty so it doesn't get saved in the post content
        },
    },
    
  2. In the example prop, make sure cover is set to a valid image URL:

    example: {
        attributes: {
            cover: 'https://example.com/path/to/preview-image.jpg',
        },
        viewportWidth: 800,
    },
    
  3. Start your edit function like so:

    if ( props.attributes.cover ) {
        return <img src={ props.attributes.cover } />;
    }
    
4
  • 1
    Amazing @Sally CJ ... It worked. Thank you so much .... You are awesome :-) Commented Oct 11, 2022 at 20:25
  • You're welcome! PS: I edited your question/post - I added the 2nd quoted text in my answer, which I forgot to do so earlier.. 🤦‍♀️
    – Sally CJ
    Commented Oct 12, 2022 at 0:27
  • 1
    Thank you @SallyCJ - This also helped me out!!
    – klewis
    Commented Apr 6, 2023 at 0:43
  • This solution doesn’t seem to work anymore
    – Paul
    Commented Oct 22 at 9:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.