Inyectar variables de JavaScript en el editor de bloques personalizado de WordPress

5 minutos de lectura

avatar de usuario de lejahmie
lejahmie

Estoy creando algunos bloques personalizados en un tema y tengo un problema. A veces tengo la necesidad de pasar algunos datos personalizados a mis bloques en el editor de bloques.

En otras palabras, necesito que los datos estén disponibles en blocks/myBlock/index.js (el script del editor).

Registro mis bloques, con la nueva forma recomendada, register_block_type(__DIR__ . '/build/blocks/myBlock');que básicamente carga el archivo block.json que luego registra todos los scripts de editor, frontend y render definidos allí.

En mi caso se compone de:

"editorScript": "file:./index.js",
  "style": [
    "file:./style.css"
  ],
  "render": "file:./render.php"

Uno pensaría que podría usar la función wp_add_inline_script en el gancho admin_enqueue_scripts, pero no parece funcionar. Se activa Hook, pero no se agregan scripts en línea. Mi mejor conjetura después de algunas investigaciones es que los scripts de bloque se cargan demasiado pronto y el wp_add_inline_script se activa después de que el script ya se haya cargado o algo así, según los comentarios en la documentación oficial; https://developer.wordpress.org/reference/functions/wp_add_inline_script/#comment-5828

Ejemplo:

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

E incluso fuerza bruta en los scripts usando admin_head-hook, como sugirió el comentario, aunque usó wp_footer como ejemplo, tampoco parece funcionar. Luego puedo ver mi secuencia de comandos en línea cargada, pero se carga después de la secuencia de comandos del editor de bloques y, para entonces, no se puede acceder a ninguno de los datos accesibles a través de la secuencia de comandos inlien.

Ejemplo:

add_action('admin_head', function () {
    echo '<script>window.myBlockConfig = ' . json_encode(array(
     'foo' => 'bar'
    )) . '</script>';
});

Script en línea cargado después de los scripts que necesitan los datos

Entonces, ¿cuál sería la forma “correcta” de hacer esto?

ACTUALIZACIÓN 1:

La única forma que he encontrado para resolver esto es usar la API REST de WordPress, por ejemplo.

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

Y luego, en mi secuencia de comandos del editor de bloques, puedo buscarlo;

const config = await apiFetch({
   path: `/myBlock/v1/config`,
});

Pero aún la pregunta es; ¿Cuál sería la forma “correcta” de hacer esto? ¿Tal vez es mejor usar la API? React backend está muy centrado en la API, por lo que tiene sentido, pero “precargar la configuración” lo hace más rápido. Así que es pro/contra, supongo.

Todavía me resulta extraño que parezca imposible que cualquier gancho cargue etiquetas de script antes que bloques.

Gracias por tu tiempo 🙂

ACTUALIZACIÓN 2:

Resulta que soy un idiota como siempre. El nombre del identificador utilizado en wp_add_inline_script. Usé la identificación completa del script como se ve en el código fuente; my-namespace-my-block-script-jspero -js WordPress lo agrega en los scripts y no forma parte del nombre del identificador. Así que debería ser simplemente my-namespace-my-block-editor-script. Y entonces simplemente funciona…

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

La respuesta de @Ruvee me ayudó a darme cuenta de esto y está marcada como respuesta “correcta”.

  • Resulta que mi problema fue, bastante estúpidamente, el nombre del identificador utilizado en wp_add_inline_script. Usé la identificación completa del script como se ve en el código fuente; myBlock-editor-script-jspero -js WordPress lo agrega en los scripts y no forma parte del nombre del identificador. Así que debería ser simplemente myBlock-editor-script. Y entonces simplemente funciona…

    – lejahmie

    27 abr a las 21:23

Avatar de usuario de Ruvee
ruvee

No hay suficiente espacio en la sección de comentarios, ¡así que escribiré mi respuesta aquí!

he estado jugando con "Gutenberg blocks" Desde hace bastante tiempo, ¡creo que podría ser capaz de ayudarte!

Respuesta corta:

Sí, hay una forma mejor, o como tú dices, “correcta” de hacer esto y no hay necesidad de una llamada api adicional, ¡aunque podría ser una opción en ciertas situaciones! Pero lo que estás buscando, es wp_localize_scriptDocumentos


Respuesta más detallada:

Dado que no proporcionó ningún código específico y solo hizo algunas preguntas generales, le daré los pasos generales que seguiría cuando intente acceder javascript variables en el ámbito global!

Registrando tu bloque con initDocumentos gancho de acción, así:

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

Cuando carga publicaciones que contienen esos bloques en el lado del administrador, podrá acceder a esas variables globales. Acabo de probar y aquí hay una captura de pantalla de mi parte

ingrese la descripción de la imagen aquí

Nota:

  • Primero, tienes que registrar un javascript fileusando wp_register_script función, con el fin de utilizar su nombre como referencia en wp_localize_script función.
  • También podría usar algunas comprobaciones condicionales como is_adminDocumentos para reducir la carga de sus variables globales.

Podría haber sido más específico y darle más detalles si hubiera proporcionado más detalles sobre su pregunta, pero creo que las referencias que le acabo de dar serían suficientes para llevarlo en la dirección correcta.

  • ¡Gracias! ¡Tu respuesta ayudó! Resultó wp_add_inline_script funciona tan bien como wp_localize_script. Resulta que mi problema era el nombre del controlador. solía myBlock-editor-script-js pero -js WordPress lo agrega automáticamente. Así que el controlador correcto es myBlock-editor-script. E incluso funciona cuando se usa la forma blocks.json para registrar su bloque. register_block_type('path/to/build/blocks/myBlock');

    – lejahmie

    27 abr a las 21:34

¿Ha sido útil esta solución?