Injecting JavaScript variables to custom WordPress block editor

huangapple go评论55阅读模式
英文:

Injecting JavaScript variables to custom WordPress block editor

问题

I can provide translations for the code-related content:

  1. 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.
    我使用推荐的新方法注册我的块,即register_block_type(__DIR__ . '/build/blocks/myBlock');,它基本上加载block.json文件,然后在那里注册所有定义的编辑器、前端和渲染脚本。

  2. 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.
    人们可能会认为我可以在admin_enqueue_scripts挂钩中使用wp_add_inline_script函数,但似乎不起作用。挂钩被触发,但没有添加内联脚本。

  3. And even brute-forcing in the scripts using admin_head-hook, as the comment suggested even though it used wp_footer as an example, does not seem to work either.
    即使使用admin_head挂钩强制添加脚本,如评论中建议的,尽管示例中使用了wp_footer,但似乎也不起作用。

  4. So what would be the "correct" way to do this?
    那么,有什么“正确”的方法可以做到这一点?

  5. 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 the source code; my-namespace-my-block-script-js, but -js is added by WordPress on scripts and is not part of the handle name.
    结果,像往常一样,我是个笨蛋。在wp_add_inline_script中使用的句柄名称。我使用了在源代码中看到的完整脚本ID; my-namespace-my-block-script-js,但是-js是由WordPress在脚本上添加的,不是句柄名称的一部分。所以它应该简单地是my-namespace-my-block-editor-script。然后它就可以工作了。

Please let me know if you need further assistance with these translations.

英文:

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>';
});

Injecting JavaScript variables to custom WordPress block editor

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 Injecting JavaScript variables to custom WordPress block editor

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.

答案1

得分: 3

以下是您要翻译的内容:

"Not enough room in the comments section, so I'll write my response here!

I've been tinkering around with 'Gutenberg blocks' for quite sometime now, I think I might be able to help you out!

Short answer:

Yes, there is a better, or as you put it, 'correct' way of doing this and no need for an extra api call, although it could be an option in certain situations! But what you're looking for, is wp_localize_scriptDocs


More detailed answer:

Since you haven't provided any specific code and just asked some general questions I'll give you general steps I would take when I'm trying to access javascript variables in the global scope!

Registering your block with initDocs action hook, like this:

add_action('init', 'your_block_admin_assets');

function your_block_admin_assets()
{
  // This is a javascript file you would need as a 'handle' when you use wp_localize_script function
  wp_register_script('your-new-blocktype', 'path/to/js/file.js', array('wp-blocks', 'wp-element', 'wp-editor'));

  // Inside this function you would need to use above js file name you just registered
  register_block_type('name_of_your_block', array(
    'editor_script' => 'your-new-blocktype',
    'render_callback' => ('your_HTML_callback')
  ));

  // Use the name of the script you registered above as first argument and second argument would be a name you pick and choose to access your data in the global scope (i.e ruveeTestData.root_url)
  wp_localize_script('your-new-blocktype', 'ruveeTestData', array(
    'root_url' => get_site_url(),
    'dummy_data' => 'dummy_stuff'
  ));
}

When you load posts that contain those block on the admin side, you would be able to access those global variables. I just tested and here's a screenshot from my end

Injecting JavaScript variables to custom WordPress block editor

Note:

  • First, you have to register a javascript file, using wp_register_script function, in order to use its name as a reference in wp_localize_script function.
  • You could also use some conditional checks like is_adminDocs to narrow down the loading of your global variables.

I could have been more specifics and given you more details if you had provided more details on your question, but I think the references I just gave you, would be sufficient to get you going in the right direction!"

英文:

Not enough room in the comments section, so I'll write my response here!

I've been tinkering around with "Gutenberg blocks" for quite sometime now, I think I might be able to help you out!

Short answer:

>Yes, there is a better, or as you put it, "correct" way of doing this and no need for an extra api call, although it could be an option in certain situations! But what you're looking for, is wp_localize_script<sup>Docs</sup>


More detailed answer:

Since you haven't provided any specific code and just asked some general questions I'll give you general steps I would take when I'm trying to access javascript variables in the global scope!

Registering your block with init<sup>Docs</sup> action hook, like this:

add_action(&#39;init&#39;, &#39;your_block_admin_assets&#39;);

function your_block_admin_assets()
{
  // This is a javascript file you would need as a &quot;handle&quot; when you use wp_localize_script function
  wp_register_script(&#39;your-new-blocktype&#39;, &#39;path/to/js/file.js&#39;, array(&#39;wp-blocks&#39;, &#39;wp-element&#39;, &#39;wp-editor&#39;));

  // Inside this function you would need to use above js file name you just registered
  register_block_type(&#39;name_of_your_block&#39;, array(
    &#39;editor_script&#39; =&gt; &#39;your-new-blocktype&#39;,
    &#39;render_callback&#39; =&gt; (&#39;your_HTML_callback&#39;)
  ));

  // Use the name of the script you registered above as first argument and second argument would be a name you pick and choose to access your data in the global scope (i.e ruveeTestData.root_url)
  wp_localize_script(&#39;your-new-blocktype&#39;, &#39;ruveeTestData&#39;, array(
    &#39;root_url&#39; =&gt; get_site_url(),
    &#39;dummy_data&#39; =&gt; &#39;dummy_stuff&#39;
  ));
}

When you load posts that contain those block on the admin side, you would be able to access those global variables. I just tested and here's a screenshot from my end

Injecting JavaScript variables to custom WordPress block editor

Note:

  • First, you have to register a javascript file, using wp_register_script function, in order to use its name as a reference in wp_localize_script function.
  • You could also use some conditional checks like is_admin<sup>Docs</sup> to narrow down the loading of your global variables.

I could have been more specifics and given you more details if you had provided more details on your question, but I think the references I just gave you, would be sufficient to get you going in the right direction!

huangapple
  • 本文由 发表于 2023年4月17日 23:14:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76036666.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定