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.
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<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>