Is it possible to allow only a specific variant inside an InnerBlock?
const innerBlockProps = useInnerBlocksProps( blockProps, {
allowedBlocks: [ 'woocommerce/product-collection' ],
} );
This works. But woocommerce/product-collection
has multiple variants, and I want the user to be able to only set a specific variant inside a custom block.
This is not working for me:
const innerBlockProps = useInnerBlocksProps( blockProps, {
allowedBlocks: [ 'woocommerce/product-collection/hand-picked' ], // specific variant.
} );
Anyone knows if this is possible?
Is it possible to allow only a specific variant inside an InnerBlock?
const innerBlockProps = useInnerBlocksProps( blockProps, {
allowedBlocks: [ 'woocommerce/product-collection' ],
} );
This works. But woocommerce/product-collection
has multiple variants, and I want the user to be able to only set a specific variant inside a custom block.
This is not working for me:
const innerBlockProps = useInnerBlocksProps( blockProps, {
allowedBlocks: [ 'woocommerce/product-collection/hand-picked' ], // specific variant.
} );
Anyone knows if this is possible?
First: It is impossible
allowedBlocks
only accepts block names as strings — not specific variations or object definitions.
Second: What’s the correct approach?
Use the base block name, then define the variation via className
or attributes in the template
.
How to find a variation's className? Insert the block (e.g., core/group) and select the desired variation.
Go to the sidebar → Advanced → copy the className
it uses.
Enter the className
in the code
<div {...blockProps}>
<InnerBlocks
allowedBlocks={['core/group']}
template={[
[
'core/group',
{ className: 'is-style-boxed-1' }
]
]}
/>
</div>
Example of application in your code.
const innerBlockProps = useInnerBlocksProps(blockProps, {
allowedBlocks: ['core/group'],
template: [['core/group', { className: 'is-style-boxed-1' }]],
});
Replace core/group
and is-style-boxed-1
with your desired block and variation class.
Not only className
, but other attributes like spacing, margin, padding, etc. can also be added. Since I don't know the content of woocommerce/product-collection
, I only show className
, and className
is also an attribute that defines the variation.
You cannot directly restrict InnerBlocks
to a specific block variant (e.g., woocommerce/product-collection/hand-picked
) using the allowedBlocks
property, as it only supports base block types (e.g., woocommerce/product-collection
). Variants are not treated as distinct blocks in the WordPress block editor's API.
The allowedBlocks
property in useInnerBlocksProps
filters blocks by their registered block type, not by their variants. Block variants (like hand-picked
for woocommerce/product-collection
) are essentially predefined configurations of the same block type, sharing the same block name. Thus, specifying woocommerce/product-collection/hand-picked
in allowedBlocks
is invalid because it’s not a registered block type.
Here are some approaches to achieve your goal of restricting users to a specific variant:
Custom Block Wrapper with Locked Variant
woocommerce/product-collection
block.template
property in useInnerBlocksProps
to predefine the block with the desired variant.templateLock: 'all'
to prevent users from changing the block or its variant.const innerBlockProps = useInnerBlocksProps(blockProps, {
allowedBlocks: ['woocommerce/product-collection'],
template: [
[
'woocommerce/product-collection',
{ variation: 'hand-picked' }, // Set the specific variant
],
],
templateLock: 'all', // Lock the template to prevent changes
});
Pros: Ensures the block is inserted with the desired variant and prevents variant switching.
Cons: Users cannot add or remove blocks within the InnerBlocks
area.
Programmatic Variant Enforcement
woocommerce/product-collection
block in allowedBlocks
.Example:
import { useEffect } from '@wordpress/element';
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
export default function Edit({ attributes, setAttributes, clientId }) {
const blockProps = useBlockProps();
const innerBlockProps = useInnerBlocksProps(blockProps, {
allowedBlocks: ['woocommerce/product-collection'],
});
useEffect(() => {
const blocks = wp.data.select('core/block-editor').getBlocks(clientId);
blocks.forEach((block) => {
if (
block.name === 'woocommerce/product-collection' &&
block.attributes.variation !== 'hand-picked'
) {
wp.data
.dispatch('core/block-editor')
.updateBlockAttributes(block.clientId, { variation: 'hand-picked' });
}
});
}, [clientId]);
return <div {...innerBlockProps} />;
}
Pros: Dynamically enforces the variant without locking the template. Cons: Brittle, as users can still switch variants via the UI, requiring constant monitoring. Also, it may cause unexpected behavior if the block’s attributes change frequently.
Custom Block with Hardcoded Variant
InnerBlocks
, create a custom block that renders the woocommerce/product-collection
block with the hand-picked
variant hardcoded in its attributes.renderCallback
or client-side rendering to ensure only the desired variant is used.Example:
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps } from '@wordpress/block-editor';
registerBlockType('my-custom/hand-picked-collection', {
title: 'Hand-Picked Product Collection',
category: 'woocommerce',
edit: () => {
const blockProps = useBlockProps();
return (
<div {...blockProps}>
<InnerBlocks
allowedBlocks={['woocommerce/product-collection']}
template={[
['woocommerce/product-collection', { variation: 'hand-picked' }],
]}
templateLock="all"
/>
</div>
);
},
save: () => <InnerBlocks.Content />,
});
Pros: Full control over the block’s behavior and variant. Cons: Less flexible if you need to support multiple variants or dynamic configurations.
Block Validation on Save
hand-picked
.validateBlock
hook or a custom validation function.Example (client-side validation):
import { addFilter } from '@wordpress/hooks';
addFilter(
'blocks.getBlockAttributes',
'my-custom/validate-product-collection',
(attributes, blockType, { clientId }) => {
if (blockType.name === 'woocommerce/product-collection') {
if (attributes.variation !== 'hand-picked') {
wp.data
.dispatch('core/notices')
.createErrorNotice('Only the hand-picked variant is allowed.');
return { ...attributes, variation: 'hand-picked' };
}
}
return attributes;
}
);
Pros: Provides feedback to users and enforces the variant. Cons: Complex to implement and may not prevent UI-based variant changes before validation.
woocommerce/product-collection
block’s variants are managed via attributes (e.g., variation: 'hand-picked'
). Check the block’s documentation or source code for supported attributes and ensure your solution aligns with WooCommerce’s updates.The Custom Block Wrapper with Locked Variant (Option 1) is the most robust and user-friendly approach. It ensures the hand-picked
variant is used without requiring complex validation or monitoring. If you need more flexibility, combine it with Programmatic Variant Enforcement (Option 2) to handle edge cases.
If you share more details about your use case (e.g., why you need to restrict the variant, whether users need to add multiple blocks), I can refine the solution further. Would you like me to elaborate on any of these approaches or explore another angle?