Specify exact parent child relationship between two blocks
-
20-05-2021 - |
Pregunta
I have built two blocks for displaying a list of feature cards.
Block 1: Feature Cards (the container element)
(function (blocks, element, blockEditor) {
var el = element.createElement;
var InnerBlocks = blockEditor.InnerBlocks;
blocks.registerBlockType('feature-cards', {
title: 'Feature Cards',
icon: 'universal-access-alt',
category: 'layout',
example: {},
edit: function (props) {
return el('div', { className: 'feature-cards' },
el(InnerBlocks)
);
},
save: function (props) {
return el('div', { className: 'feature-cards' },
el(InnerBlocks.Content)
);
},
});
})(window.wp.blocks, window.wp.element, window.wp.blockEditor);
Block 2: Feature Card (the card itself with editable content)
(function (blocks, editor, element, blockEditor) {
var el = element.createElement;
var RichText = editor.RichText;
var InnerBlocks = blockEditor.InnerBlocks;
blocks.registerBlockType('feature-card', {
parent: ['feature-cards'],
title: 'Feature Card',
icon: 'universal-access-alt',
category: 'layout',
example: {},
attributes: {
content: {
type: 'array',
source: 'children',
selector: 'h3',
},
},
edit: function (props) {
var content = props.attributes.content;
function onChangeContent( newContent ) {
props.setAttributes( { content: newContent } );
}
return el('div', { className: 'feature-card' },
el('div', { className: 'feature-card__icon' }, el(InnerBlocks)),
el( RichText, {
tagName: 'h3',
className: 'feature-card__title',
onChange: onChangeContent,
value: content,
} )
);
},
save: function (props) {
return el('div', { className: 'feature-card' },
el('div', { className: 'feature-card__icon' }, el(InnerBlocks.Content)),
el( RichText.Content, {
tagName: 'h3',
className: 'feature-card__title',
value: props.attributes.content,
} )
);
},
});
})(window.wp.blocks, window.wp.editor, window.wp.element, window.wp.blockEditor);
As you can see I have specified that the feature-cards
are the parent for the feature-card
so that the card blocks can only be used inside the parent block.
However there's a couple of issues that I'm not sure how best to resolve:
First I want to make it so that the ONLY block that can be added as a child block of the feature-cards
is the child block. How can I enforce this? As the parent block displays a grid with the expectation of the cards (so other blocks don't work inside here).
Second as stated above the parent block displays a grid... but when inside the editor it seems WordPress adds some wrapper elements like:
Which causes the grid to break when viewing the block inside the editor because it applies the grid CSS to the wrapper... is there anyway around this so that it displays correctly?
Edit: I've been looking at the Social Icons block that's included in the WordPress core to see how they get around this issue and it seems that they don't apply the CSS in the editor-side for that block as they use flexbox to align them but that's only seen on the front-end.
Solución
I'm not sure about the second one (removing the wrappers), but as for limiting the allowed blocks:
First I want to make it so that the ONLY block that can be added as a child block of the
feature-cards
is the child block. How can I enforce this?
You can use the allowedBlocks
property of InnerBlocks
like so:
// In the edit() function of the feature-cards block type:
el( InnerBlocks, { allowedBlocks: [ 'feature-card' ] } )
And you should know that wp.editor.RichText
is deprecated, so use wp.blockEditor.RichText
instead. So in your feature-card
block type, you'd use var RichText = blockEditor.RichText;
and not var RichText = editor.RichText;
.
Also, you might also want to use useBlockProps
in your code. :)