-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Block Bindings: Create utils to update or remove bindings #64102
Changes from all commits
1279f82
5d44e50
92aa448
10d3f82
11a35b9
9373c14
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useDispatch, useSelect } from '@wordpress/data'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { store as blockEditorStore } from '../store'; | ||
import { useBlockEditContext } from '../components/block-edit'; | ||
|
||
export function useBlockBindingsUtils() { | ||
const { clientId } = useBlockEditContext(); | ||
const { updateBlockAttributes } = useDispatch( blockEditorStore ); | ||
const { getBlockAttributes } = useSelect( blockEditorStore ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be more optimal to have: const { getBlockAttributes } = useRegistry().select( blockEditorStore ); See more in this guide. |
||
|
||
/** | ||
* Updates the value of the bindings connected to block attributes. | ||
* It removes the binding when the new value is `undefined`. | ||
* | ||
* @param {Object} bindings Bindings including the attributes to update and the new object. | ||
* @param {string} bindings.source The source name to connect to. | ||
* @param {Object} [bindings.args] Object containing the arguments needed by the source. | ||
* | ||
* @example | ||
* ```js | ||
* import { useBlockBindingsUtils } from '@wordpress/block-editor' | ||
* | ||
* const { updateBlockBindings } = useBlockBindingsUtils(); | ||
* updateBlockBindings( { | ||
* url: { | ||
* source: 'core/post-meta', | ||
* args: { | ||
* key: 'url_custom_field', | ||
* }, | ||
* }, | ||
* alt: { | ||
* source: 'core/post-meta', | ||
* args: { | ||
* key: 'text_custom_field', | ||
* }, | ||
* } | ||
* } ); | ||
* ``` | ||
*/ | ||
const updateBlockBindings = ( bindings ) => { | ||
const { metadata } = getBlockAttributes( clientId ); | ||
const newBindings = { ...metadata?.bindings }; | ||
Object.entries( bindings ).forEach( ( [ attribute, binding ] ) => { | ||
if ( ! binding && newBindings[ attribute ] ) { | ||
delete newBindings[ attribute ]; | ||
return; | ||
} | ||
newBindings[ attribute ] = binding; | ||
} ); | ||
|
||
const newMetadata = { | ||
...metadata, | ||
bindings: newBindings, | ||
}; | ||
|
||
if ( Object.keys( newMetadata.bindings ).length === 0 ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here and in other places it would increase the readability if the helper function was present: function isObjectEmpty( object ) {
return ! object || Object.keys( object ).length === 0;
}
// later
if ( isObjectEmpty( newMetadata.bindings ) ) { This could also be further refactored so it doesn't require the step to remove the undefined key: const newMetadata = {
...metadata,
...( ! isObjectEmpty( newBindings ) && {
bindings: newBindings,
} ),
}; |
||
delete newMetadata.bindings; | ||
} | ||
|
||
updateBlockAttributes( clientId, { | ||
metadata: | ||
Object.keys( newMetadata ).length === 0 | ||
? undefined | ||
: newMetadata, | ||
} ); | ||
}; | ||
|
||
/** | ||
* Removes the bindings property of the `metadata` attribute. | ||
* | ||
* @example | ||
* ```js | ||
* import { useBlockBindingsUtils } from '@wordpress/block-editor' | ||
* | ||
* const { removeAllBlockBindings } = useBlockBindingsUtils(); | ||
* removeAllBlockBindings(); | ||
* ``` | ||
*/ | ||
const removeAllBlockBindings = () => { | ||
const { metadata } = getBlockAttributes( clientId ); | ||
const newMetadata = { ...metadata }; | ||
delete newMetadata.bindings; | ||
Comment on lines
+86
to
+88
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That could be a single line: const { metadata: { bindings, ...metadata } } = getBlockAttributes( clientId ); |
||
updateBlockAttributes( clientId, { | ||
metadata: | ||
Object.keys( newMetadata ).length === 0 | ||
? undefined | ||
: newMetadata, | ||
} ); | ||
}; | ||
|
||
return { updateBlockBindings, removeAllBlockBindings }; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why were we using the
label
here before? It seems like that was brittle. It appears that this change is unrelated to the adding of the utils in this PR, and is just an additional code cleanup, and it looks good. I'm just curious.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that we were just using the values of the
registeredSources
object instead of their keys.I'm not sure if if sources label were always the same as the registeredSources key, but this approach seems safer, as the label should allow whitespaces or uppercases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the name wasn't exposed before. But this seemed safer to me as well.