diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js
index 5c002613831ce..694c9c1c0bb3c 100644
--- a/packages/block-editor/src/hooks/block-bindings.js
+++ b/packages/block-editor/src/hooks/block-bindings.js
@@ -5,6 +5,7 @@ import { __ } from '@wordpress/i18n';
import {
getBlockBindingsSource,
getBlockBindingsSources,
+ getBlockType,
} from '@wordpress/blocks';
import {
__experimentalItemGroup as ItemGroup,
@@ -29,6 +30,7 @@ import {
import { unlock } from '../lock-unlock';
import InspectorControls from '../components/inspector-controls';
import BlockContext from '../components/block-context';
+import { useBlockEditContext } from '../components/block-edit';
import { useBlockBindingsUtils } from '../utils/block-bindings';
import { store as blockEditorStore } from '../store';
@@ -50,9 +52,20 @@ const useToolsPanelDropdownMenuProps = () => {
};
function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) {
+ const { clientId } = useBlockEditContext();
const registeredSources = getBlockBindingsSources();
const { updateBlockBindings } = useBlockBindingsUtils();
const currentKey = binding?.args?.key;
+ const attributeType = useSelect(
+ ( select ) => {
+ const { name: blockName } =
+ select( blockEditorStore ).getBlock( clientId );
+ const _attributeType =
+ getBlockType( blockName ).attributes?.[ attribute ]?.type;
+ return _attributeType === 'rich-text' ? 'string' : _attributeType;
+ },
+ [ clientId, attribute ]
+ );
return (
<>
{ Object.entries( fieldsList ).map( ( [ name, fields ], i ) => (
@@ -63,29 +76,33 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) {
{ registeredSources[ name ].label }
) }
- { Object.entries( fields ).map( ( [ key, args ] ) => (
-
- updateBlockBindings( {
- [ attribute ]: {
- source: name,
- args: { key },
- },
- } )
- }
- name={ attribute + '-binding' }
- value={ key }
- checked={ key === currentKey }
- >
-
- { args?.label }
-
-
- { args?.value }
-
-
- ) ) }
+ { Object.entries( fields )
+ .filter(
+ ( [ , args ] ) => args?.type === attributeType
+ )
+ .map( ( [ key, args ] ) => (
+
+ updateBlockBindings( {
+ [ attribute ]: {
+ source: name,
+ args: { key },
+ },
+ } )
+ }
+ name={ attribute + '-binding' }
+ value={ key }
+ checked={ key === currentKey }
+ >
+
+ { args?.label }
+
+
+ { args?.value }
+
+
+ ) ) }
{ i !== Object.keys( fieldsList ).length - 1 && (
diff --git a/packages/e2e-tests/plugins/block-bindings.php b/packages/e2e-tests/plugins/block-bindings.php
index ffbe50ab3cc90..b86673c2c523d 100644
--- a/packages/e2e-tests/plugins/block-bindings.php
+++ b/packages/e2e-tests/plugins/block-bindings.php
@@ -21,14 +21,17 @@ function gutenberg_test_block_bindings_registration() {
'text_field' => array(
'label' => 'Text Field Label',
'value' => 'Text Field Value',
+ 'type' => 'string',
),
'url_field' => array(
'label' => 'URL Field Label',
'value' => $testing_url,
+ 'type' => 'string',
),
'empty_field' => array(
'label' => 'Empty Field Label',
'value' => '',
+ 'type' => 'string',
),
);
@@ -106,6 +109,89 @@ function gutenberg_test_block_bindings_registration() {
'type' => 'string',
)
);
+ // Register different types of custom fields for testing.
+ register_meta(
+ 'post',
+ 'string_custom_field',
+ array(
+ 'label' => 'String custom field',
+ 'default' => '',
+ 'show_in_rest' => true,
+ 'single' => true,
+ 'type' => 'string',
+ )
+ );
+ register_meta(
+ 'post',
+ 'object_custom_field',
+ array(
+ 'label' => 'Object custom field',
+ 'show_in_rest' => array(
+ 'schema' => array(
+ 'type' => 'object',
+ 'properties' => array(
+ 'foo' => array(
+ 'type' => 'string',
+ ),
+ ),
+ ),
+ ),
+ 'single' => true,
+ 'type' => 'object',
+ )
+ );
+ register_meta(
+ 'post',
+ 'array_custom_field',
+ array(
+ 'label' => 'Array custom field',
+ 'show_in_rest' => array(
+ 'schema' => array(
+ 'type' => 'array',
+ 'items' => array(
+ 'type' => 'string',
+ ),
+ ),
+ ),
+ 'single' => true,
+ 'type' => 'array',
+ 'default' => array(),
+ )
+ );
+ register_meta(
+ 'post',
+ 'number',
+ array(
+ 'label' => 'Number custom field',
+ 'type' => 'number',
+ 'show_in_rest' => true,
+ 'single' => true,
+ 'default' => 5.5,
+ )
+ );
+ register_meta(
+ 'post',
+ 'integer',
+ array(
+ 'label' => 'Integer custom field',
+ 'type' => 'integer',
+ 'show_in_rest' => true,
+ 'single' => true,
+ 'default' => 5,
+ )
+ );
+ register_meta(
+ 'post',
+ 'boolean',
+ array(
+ 'label' => 'Boolean custom field',
+ 'type' => 'boolean',
+ 'show_in_rest' => true,
+ 'single' => true,
+ 'default' => true,
+ )
+ );
+
// Register CPT custom fields.
register_meta(
'post',
diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js
index 9198ac0fe41e1..a3602ce7d6207 100644
--- a/packages/editor/src/bindings/post-meta.js
+++ b/packages/editor/src/bindings/post-meta.js
@@ -60,6 +60,7 @@ function getPostMetaFields( select, context ) {
entityMetaValues?.[ key ] ??
// When using the default, an empty string IS NOT a valid value.
( props.default || undefined ),
+ type: props.type,
};
}
} );
diff --git a/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js b/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js
index d82def6feb66b..32334bfc777f2 100644
--- a/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js
+++ b/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js
@@ -547,5 +547,54 @@ test.describe( 'Post Meta source', () => {
.filter( { hasText: 'Movie field label' } );
await expect( movieField ).toBeVisible();
} );
+ test( 'should not be possible to connect non-supported fields through the attributes panel', async ( {
+ editor,
+ page,
+ } ) => {
+ await editor.insertBlock( {
+ name: 'core/paragraph',
+ } );
+ await page.getByLabel( 'Attributes options' ).click();
+ await page
+ .getByRole( 'menuitemcheckbox', {
+ name: 'Show content',
+ } )
+ .click();
+ await page
+ .getByRole( 'button', {
+ name: 'content',
+ } )
+ .click();
+ await expect(
+ page.getByRole( 'menuitemradio', {
+ name: 'String custom field',
+ } )
+ ).toBeVisible();
+ await expect(
+ page.getByRole( 'menuitemradio', {
+ name: 'Number custom field',
+ } )
+ ).toBeHidden();
+ await expect(
+ page.getByRole( 'menuitemradio', {
+ name: 'Integer custom field',
+ } )
+ ).toBeHidden();
+ await expect(
+ page.getByRole( 'menuitemradio', {
+ name: 'Boolean custom field',
+ } )
+ ).toBeHidden();
+ await expect(
+ page.getByRole( 'menuitemradio', {
+ name: 'Object custom field',
+ } )
+ ).toBeHidden();
+ await expect(
+ page.getByRole( 'menuitemradio', {
+ name: 'Array custom field',
+ } )
+ ).toBeHidden();
+ } );
} );
} );