I am creating a few custom blocks in a theme, and I have a problem. Sometimes I have a need to pass some custom data to my blocks in the blocks editor.
In other words, I need data to be available in the blocks/myBlock/index.js (the editor script).
I register my blocks, with the recommended new way, register_block_type(__DIR__ . '/build/blocks/myBlock');
, that basically loads the block.json file that then registers all the editor, frontend and render scripts defined there.
In my case it is composed of:
"editorScript": "file:./index.js",
"style": [
"file:./style.css"
],
"render": "file:./render.php"
One would think I could use the function wp_add_inline_script
in the hook admin_enqueue_scripts
, but it does not seem to work. Hook is triggered, but no inline scripts are added. My best guess after some investigation is that block-scripts are loaded too early, and the wp_add_inline_script
is triggered after script already has been loaded or something, according to comments in official documentation; https://developer.wordpress.org/reference/functions/wp_add_inline_script/#comment-5828
Example:
add_action('admin_enqueue_scripts', function () {
wp_add_inline_script('my-namespace-my-block-editor-script-js', 'window.myBlockConfig = ' . json_encode(array(
'foo' => 'bar',
)), 'before');
});
And even brute-forcing in the scripts using admin_head
-hook, as comment suggested even though it used wp_footer as example, does not seem to work either. I can then see my inline script loaded, but it is loaded after block-editor-script and by then none of the data made accessible via inlien script is reachable.
Example:
add_action('admin_head', function () {
echo '<script>window.myBlockConfig = ' . json_encode(array(
'foo' => 'bar'
)) . '</script>';
});
So what would be the "correct" way to do this?
UPDATE 1:
Only way I've found to solve this is using Wordpress REST API, eg.
function myBlockRestApiGetConfig($request)
{
$response = array(
'foo' => 'bar',
);
return rest_ensure_response($response);
}
add_action('rest_api_init', function () {
register_rest_route('myBlock/v1', '/config', array(
'methods' => 'GET',
'callback' => 'myBlockRestApiGetConfig',
));
});
And then in my blocks editor script I can fetch it;
const config = await apiFetch({
path: `/myBlock/v1/config`,
});
But still question is; what would be the "correct" way to do this? Maybe it is better to use the API? React backend is very API centric so it makes sense, but "preloading config" makes it faster. So it is pro/con I guess.
I still find it strange that it seems impossible to any hooks to load any script-tags before blocks.
Thank you for your time :-)
UPDATE 2:
Turns out I am an idiot as usual. The handle name used in wp_add_inline_script
. I used the full script id as seen in source code; my-namespace-my-block-script-js
, but -js
is added by Wordpress on scripts and is not part of handle name. So it should be simply my-namespace-my-block-editor-script
. And then it just works...
add_action('admin_enqueue_scripts', function () {
// Add pre-loaded data for my-namespace/my-block
wp_add_inline_script('my-namespace-my-block-editor-script', 'window.myBlockConfig = ' . json_encode(array(
'foo' => 'bar',
)), 'before');
});
Answer by @Ruvee helped me realise this, and is marked as "correct" answer.
wp_add_inline_script
. I used the full script id as seen in source code;myBlock-editor-script-js
, but-js
is added by Wordpress on scripts and is not part of handle name. So it should be simplymyBlock-editor-script
. And then it just works... – Theisblock.json
file has{..., "name": "ifolders/image-gallery", ...}
, so thewp_localize_script
will be like thiswp_localize_script ('ifolders-image-gallery-editor-script', ..., ...)
. As you can see the"ifolders/image-gallery"
converted to"ifolders-image-gallery-editor-script"
. Hope it will help to someone. – Neoclassic