I am trying to create several custom blocks within Gutenberg. It is only allowing me to register one at a time.
I have tried combining recipe_card_block()
and first_block()
but that doesn't help.
Both blocks work correctly individually. If I remove recipe_card_block()
, first_block()
will appear in the inserter (and vice versa). However, when both are present only the first one will show up. Changing the order in which they are registered affects which one appears.
It seems to me they are somehow overwriting each other, but I don't see how that's happening.
Here is the code in functions.php
.
function recipe_card_block(){
wp_register_script(
'recipe-card-script', // name of script
get_template_directory_uri() . '/js/recipe-card.js', // path to script
array( 'wp-blocks', 'wp-element', 'wp-editor', 'wp-components' ) // dependencies
);
wp_register_style(
'recipe-card-style',
get_template_directory_uri() . '/css/recipe-card-style.css',
array( 'wp-edit-blocks' )
);
register_block_type('gadam/recipe-card', array(
'editor_script' => 'recipe-card-script', // default script / script to define behavior within the editor
'style' => 'recipe-card-style' // default styles
) );
}
add_action( 'init', 'recipe_card_block' );
function first_block(){
wp_register_script(
'first-block-script', // name of script
get_template_directory_uri() . '/js/first-block.js', // path to script
array( 'wp-blocks', 'wp-element', 'wp-editor' ) // dependencies
);
// styles for editor view
wp_register_style(
'first-block-editor-style',
get_template_directory_uri() . '/css/first-block-editor-style.css',
array( 'wp-edit-blocks' )
);
// default styles
wp_register_style(
'first-block-style',
get_template_directory_uri() . '/css/first-block-style.css',
array( 'wp-edit-blocks' )
);
register_block_type('gadam/first-block', array(
'editor_script' => 'first-block-script', // default script / script to define behavior within the editor
'editor_style' => 'first-block-editor-style', // styles for editor view
'style' => 'first-block-style' // default styles
) );
}
add_action( 'init', 'first_block' );
This is the code in first-block.js
const { registerBlockType } = wp.blocks;
const { RichText, BlockControls, InspectorControls, AlignmentToolbar, FontSizePicker } = wp.editor;
const { Fragment } = wp.element;
registerBlockType( 'gadam/first-block', {
title: 'First Block',
icon: 'welcome-learn-more',
category: 'custom-blocks',
attributes: {
content: {
type: 'string',
source: 'html',
selector: 'p'
},
alignment: {
type: 'string'
},
fontSize: {
type: 'number',
default: 18
}
},
edit( { attributes, className, setAttributes } ) {
const { content, alignment, fontSize } = attributes;
const fontSizes = [
{
name: 'Small',
slug: 'small',
size: 14
},
{
name: 'Normal',
slug: 'normal',
size: 18
},
{
name: 'Large',
slug: 'large',
size: 24
}
];
function onChangeContent( newContent ) {
setAttributes( { content: newContent } );
}
function onChangeAlignment( newAlignment ) {
setAttributes( { alignment: newAlignment } );
}
function onChangeFontSize( newFontSize ) {
setAttributes( { fontSize: newFontSize } );
}
return (
<Fragment>
<BlockControls>
<AlignmentToolbar
value={ alignment }
onChange={ onChangeAlignment }
/>
</BlockControls>
<InspectorControls>
<AlignmentToolbar
value={ alignment }
onChange={ onChangeAlignment }
/>
<FontSizePicker
fontSizes={ fontSizes }
value={ fontSize }
onChange={ onChangeFontSize }
/>
</InspectorControls>
<RichText
key="editable"
tagName="p"
className={ className }
style={ { textAlign: alignment, fontSize: fontSize } }
onChange={ onChangeContent }
value={ content }
/>
</Fragment>
);
},
save( { attributes } ) {
const { content, alignment, fontSize } = attributes;
const baseClass = 'wp-block-gadam-first-block';
return (
<div class="container">
<div class={ baseClass }>
<RichText.Content
style={ { textAlign: alignment, fontSize: fontSize } }
value={ content }
tagName="p"
/>
</div>
</div>
);
},
} );
And finally, this is recipe-card.js
const { registerBlockType } = wp.blocks;
const { RichText, BlockControls, InspectorControls, AlignmentToolbar, FontSizePicker } = wp.editor;
const { Fragment } = wp.element;
registerBlockType( 'gadam/recipe-card', {
title: 'Recipe Card',
icon: 'index-card',
category: 'custom-blocks',
attributes: {
content: {
type: 'string',
source: 'html',
selector: 'p'
},
alignment: {
type: 'string'
},
fontSize: {
type: 'number',
default: 18
}
},
edit( { attributes, className, setAttributes } ) {
const { content, alignment, fontSize } = attributes;
const fontSizes = [
{
name: 'Small',
slug: 'small',
size: 14
},
{
name: 'Normal',
slug: 'normal',
size: 18
},
{
name: 'Large',
slug: 'large',
size: 24
}
];
function onChangeContent( newContent ) {
setAttributes( { content: newContent } );
}
function onChangeAlignment( newAlignment ) {
setAttributes( { alignment: newAlignment } );
}
function onChangeFontSize( newFontSize ) {
setAttributes( { fontSize: newFontSize } );
}
return (
<Fragment>
<BlockControls>
<AlignmentToolbar
value={ alignment }
onChange={ onChangeAlignment }
/>
</BlockControls>
<InspectorControls>
<AlignmentToolbar
value={ alignment }
onChange={ onChangeAlignment }
/>
<FontSizePicker
fontSizes={ fontSizes }
value={ fontSize }
onChange={ onChangeFontSize }
/>
</InspectorControls>
<RichText
key="editable"
tagName="p"
className={ className }
style={ { textAlign: alignment, fontSize: fontSize } }
onChange={ onChangeContent }
value={ content }
/>
</Fragment>
);
},
save( { attributes } ) {
const { content, alignment, fontSize } = attributes;
const baseClass = 'wp-block-gadam-recipe-card';
return (
<div class="container">
<div class={ baseClass }>
<RichText.Content
style={ { textAlign: alignment, fontSize: fontSize } }
value={ content }
tagName="p"
/>
</div>
</div>
);
},
} );
For anyone who may come across this in the future:
Look at the top of the two js
files I posted. The constants declared in one file are shared by all subsequently registered blocks. So what's happening is when I register first-block
the constants are defined. When I register recipe-card
it tries to define the constants at the top of the file, but they were already defined by first-block
.
The code for recipe-card.js
should remove the constants that are already defined by first-block
.
registerBlockType( 'gadam/recipe-card', {
title: 'Recipe Card',
icon: 'index-card',
category: 'custom-blocks',
attributes: {
content: {
type: 'string',
source: 'html',
selector: 'p'
},
alignment: {
type: 'string'
},
fontSize: {
type: 'number',
default: 18
}
},
edit( { attributes, className, setAttributes } ) {
const { content, alignment, fontSize } = attributes;
const fontSizes = [
{
name: 'Small',
slug: 'small',
size: 14
},
{
name: 'Normal',
slug: 'normal',
size: 18
},
{
name: 'Large',
slug: 'large',
size: 24
}
];
function onChangeContent( newContent ) {
setAttributes( { content: newContent } );
}
function onChangeAlignment( newAlignment ) {
setAttributes( { alignment: newAlignment } );
}
function onChangeFontSize( newFontSize ) {
setAttributes( { fontSize: newFontSize } );
}
return (
<Fragment>
<BlockControls>
<AlignmentToolbar
value={ alignment }
onChange={ onChangeAlignment }
/>
</BlockControls>
<InspectorControls>
<AlignmentToolbar
value={ alignment }
onChange={ onChangeAlignment }
/>
<FontSizePicker
fontSizes={ fontSizes }
value={ fontSize }
onChange={ onChangeFontSize }
/>
</InspectorControls>
<RichText
key="editable"
tagName="p"
className={ className }
style={ { textAlign: alignment, fontSize: fontSize } }
onChange={ onChangeContent }
value={ content }
/>
</Fragment>
);
},
save( { attributes } ) {
const { content, alignment, fontSize } = attributes;
const baseClass = 'wp-block-gadam-recipe-card';
return (
<div class="container">
<div class={ baseClass }>
<RichText.Content
style={ { textAlign: alignment, fontSize: fontSize } }
value={ content }
tagName="p"
/>
</div>
</div>
);
},
} );