If you're like me, trying to create your own custom Gutenberg repeater block with a text and link input field can be quite challenging. I've spent hours looking at ES5 examples like this and this, but still feel stuck.
I'm reaching out for some guidance in the right direction as I could really use some help.
Here's the code I have so far, but I'm not sure where to begin with the conversion from ES5 to ESNEXT.
Edit: Forgot to mention that I aim to do this without using ACF.
// Importing necessary libraries for this block
import { __ } from '@wordpress/i18n';
import { registerBlockType } from '@wordpress/blocks';
import { RichText, MediaUpload, InspectorControls } from '@wordpress/block-editor';
import { Button, ColorPicker, ColorPalette, Panel, PanelBody, PanelRow } from '@wordpress/components';
registerBlockType('ccm-block/banner-block', {
title: __('Banner Block'),
icon: 'format-image', // taken from Dashicons → https://developer.wordpress.org/resource/dashicons/.
category: 'layout', // e.g. common, formatting, layout widgets, embed.
keywords: [
__('Banner Block'),
__('CCM Blocks'),
],
attributes: {
mediaID: {
type: 'number'
},
mediaURL: {
type: 'string'
},
title: {
type: 'array',
source: 'children',
selector: 'h1'
},
content: {
type: 'array',
source: 'children',
selector: 'p'
},
bannerButtons: {
type: 'array',
source: 'children',
selector: '.banner-buttons',
},
items: {
type: 'array',
default: []
}
},
/**
* The edit function defines the structure of the block when viewed in the editor.
*
* @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
*
* @param {Object} props Props.
* @returns {JSXComponent} JSX Component.
*/
edit: (props) => {
const {
attributes: { mediaID, mediaURL, title, content, bannerButtons },
setAttributes, className
} = props;
const onSelectImage = (media) => {
setAttributes({
mediaURL: media.url,
mediaID: media.id,
});
};
const onChangeTitle = (value) => {
setAttributes({ title: value });
};
const onChangeContent = (value) => {
setAttributes({ content: value });
};
const onChangeBannerButtons = (value) => {
setAttributes({ bannerButtons: value });
};
return (
<div className={className}>
<div id="#home-banner">
{/* Content goes here */}
</div>
</div>
);
},
/**
* The save function determines how attributes are combined into the final markup for display.
*
* @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
*
* @param {Object} props Props.
* @returns {JSXFrontendHTML} JSX Frontend HTML.
*/
save: (props) => {
return (
<div className={ props.className }>
<div id="home-banner" style={{backgroundImage: `url(${ props.attributes.mediaURL })`}}>
{/* Saved content rendering */}
</div>
</div>
);
},
});
Edit 2: Here's my attempt at it
// Import necessary libraries for this block
import { __ } from '@wordpress/i18n';
import { registerBlockType } from '@wordpress/blocks';
import { RichText, MediaUpload, InspectorControls } from '@wordpress/block-editor';
import { Button, ColorPicker, ColorPalette, Panel, PanelBody, PanelRow } from '@wordpress/components';
/**
* Register the Custom Block
*
* @link https://wordpress.org/gutenberg/handbook/block-api/
* @param {string} name name.
* @param {Object} settings settings.
* @return {?WPBlock} The block or undefined.
*/
registerBlockType('ccm-block/banner-block', {
title: __('Banner Block'),
icon: 'format-image', // from Dashicons → https://developer.wordpress.org/resource/dashicons/.
category: 'layout', // e.g. common, formatting, layout widgets, embed.
keywords: [
__('Banner Block'),
__('CCM Blocks'),
],
attributes: {
mediaID: {
type: 'number'
},
mediaURL: {
type: 'string'
},
title: {
type: 'array',
source: 'children',
selector: 'h1'
},
content: {
type: 'array',
source: 'children',
selector: 'p'
},
bannerButtons: {
type: 'array',
source: 'children',
selector: '.banner-buttons',
},
items: {
source: 'query',
default: [],
selector: '.item',
query: {
title: {
type: 'string',
source: 'text',
selector: '.title'
},
index: {
type: 'number',
source: 'attribute',
attribute: 'data-index'
}
}
}
},
/**
* The edit function defines the structure of the block when viewed in the editor.
*
* @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
*
* @param {Object} props Props.
* @returns {JSXComponent} JSX Component.
*/
edit: (props) => {
const {
attributes: { mediaID, mediaURL, title, content, bannerButtons, items },
setAttributes, className
} = props;
const onSelectImage = (media) => {
setAttributes({
mediaURL: media.url,
mediaID: media.id,
});
};
const onChangeTitle = (value) => {
setAttributes({ title: value });
};
const onChangeContent = (value) => {
setAttributes({ content: value });
};
const onChangeBannerButtons = (value) => {
setAttributes({ bannerButtons: value });
};
return (
<div className={className}>
<div id="#home-banner">
{/* Include your editing functionality here */}
</div>
</div>
);
},
/**
* The save function determines the output markup based on the saved attributes.
*
* @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
*
* @param {Object} props Props.
* @returns {JSXFrontendHTML} JSX Frontend HTML.
*/
save: (props) => {
return (
<div className={ props.className }>
<div id="home-banner" style={{backgroundImage: `url(${ props.attributes.mediaURL })`}}>
{/* Render saved content here */}
</div>
</div>
);
},
});