Agregar JS a un tema de Drupal 8 (reemplazo de drupal_add_js)

8

En Drupal 7, puedo usar drupal_add_jsdentro del archivo template.php de un tema como una theme_preprocess_html(&$vars)función:

   drupal_add_js(drupal_get_path('theme', 'mytheme') . '/js/scripts.js',
        array(
          'group' => JS_THEME,
          'preprocess' => TRUE,
          'weight' => '999',
        ));

  $vars['scripts'] = drupal_get_js();

En Drupal 8, intenté convertir esto usando attachedel archivo .theme de mi tema como tal:

  $vars['#attached']['js'] = array(
    array(
      'data' => drupal_get_path('theme', 'mytheme') . '/js/scripts.js',
      'options' => array(
        'group' => JS_THEME,
        'preprocess' => TRUE,
        'every_page' => TRUE,
      ),
    ),
  );

... pero eso no funcionó y no hubo errores en watchdog / console o de otra manera.

De acuerdo con la página D8 API para drupal_add_js:

En desuso: a partir de Drupal 8.0. Utilice la clave # adjunta en las matrices de renderizado en su lugar.

Sin embargo, no había mucha más información que eso. Parece que drupal_add_csstambién usará este método. Sé que todavía es temprano para Drupal 8, pero esperaba dar un salto en esto.

Danny Englander
fuente
1
Solo una suposición: ¿tal vez deberías probar el enfoque de biblioteca? Y por favor, abstenerse de usar la declaración "no funcionó". ¿No odias cuando tienes que adivinar qué significa? Advertencias? Errores? ¿Nada y el archivo no está incluido?
Mołot
@ Mołot: no hubo advertencias ni errores y también revisé el perro guardián. También miré la consola en Chrome y simplemente no hubo errores, por lo que todo lo que puedo informar es "no funcionó". El informe completo de errores está activado y ciertamente obtuve una buena parte de ellos al portar este tema a Drupal 8. En cualquier caso, creo que el enfoque de la biblioteca parece ser el camino a seguir y no la respuesta que se proporciona a continuación. Voy a separar algunos módulos de Drupal 8 para ver si puedo resolverlo.
Danny Englander
Podrías haber informado "no funcionó sin errores en ...", entonces sabríamos que no hubo ninguno, y de hecho hiciste tu parte del trabajo antes de preguntar. Eso es todo lo que quería de ti :) Demasiados chicos aquí pregunta sin siquiera comprobar ...
Mołot
1
Ok, gracias, actualizado con un mejor resumen del problema. :)
Danny Englander

Respuestas:

7

Parece que puede usar hook_preprocess_pagecon adjunto como tal:

function MYTHEME_preprocess_page(&$vars, $hook) {
  $path = drupal_get_path('theme', 'MYTHEME');
     // Render the main scripts file.
  $local_js = array(
    '#attached' => array(
      'js' => array(
        $path . '/js/scripts.js' => array(
          'group' => JS_THEME,
          'weight' => 9999),
      ),
    ),
  );
  \Drupal::service('renderer')->renderRoot($local_js);
}

Esto funciona muy bien ( theme.inc usa este método), tenga en cuenta la matriz anidada adicional alrededor del peso.

Danny Englander
fuente
Código actualizado para reflejar una versión totalmente funcional, peso y todo.
Danny Englander
Exactamente lo que necesitaba, muy apreciado!
Yassin Tahtah
4

El punto clave en la documentación es este bit

Utilice la clave # adjunta en las matrices de renderizado .

El énfasis es mío.

La $variablesmatriz en una función de tema / preproceso no es una matriz de renderizado, es solo una matriz que contiene variables. Para usar #attached, necesitará algo como esto en la función de preproceso:

$vars['foo'] = array(
  '#markup' => '<p>Bar</p>',
  '#attached' => array(
    'data' => drupal_get_path('theme', 'mytheme') . '/js/scripts.js',
    'options' => array(
      'group' => JS_THEME,
      'preprocess' => TRUE,
      'every_page' => TRUE,
    ),
  ),
);

Y esto en el archivo de plantilla:

{ foo }

En otras palabras, más o menos lo mismo que en Drupal 7 (en este momento, al menos).

hook_preprocess_html()es probable que no sea el lugar correcto para este código por cierto; no olvide que los archivos js / css se representan realmente en esa plantilla, por lo que es demasiado tarde para agregar más hook_preprocess_page(), hook_preprocess_node()o el equivalente probablemente obtendrá resultados más confiables.

Consulte la página de prácticas recomendadas de Twig: funciones y plantillas de preproceso para obtener más información sobre las variables de preprocesamiento.

Clive
fuente
1
Esto es correcto: las variables pasadas a las funciones de preproceso / proceso nunca son una matriz de representación.
kiamlaluno
Con el debido respeto, simplemente estoy tratando de encontrar un reemplazo en Drupal 8 para agregar un archivo js a un tema, no estoy tratando de representar una variable en él. Incluso si lo fuera, se haría como {{ foo }}en el mundo Twig, no hay más renderizado de php / print en las plantillas de tema, es decir node.html.twig/page.html.twig
Danny Englander
1
Sí, el cerebro se congela allí, mi mal. Sin embargo, la respuesta es la misma. Solo puede usar #attacheden el contexto de una matriz de renderizado; La documentación es correcta. Debe usar el método anterior, junto con esto para preprocesar y renderizar previamente la variable, o usar el archivo .info.yml de su tema para incluir el JS. Esas son las únicas opciones que puedo decir hasta ahora, sin ir por la ruta de la biblioteca
Clive
1
Creo que el enfoque será algo similar a esto: drupalcode.org/project/drupal.git/blob/refs/heads/8.x:/core/… - vea la línea 564 que usa hook_library_infoy que Mołot implica más arriba. Tendré que jugar un poco con eso. Gracias.
Danny Englander
2

En este ejemplo, está utilizando una matriz de representación real y no una que se representa en la función misma.

De esta forma, otros módulos, temas, etc. pueden alterarlo.

/**
 * Implements hook_page_alter().
 */
function db_jacket_page_alter(&$page) {
  $page['#attached']['js'][] = drupal_get_path('theme', 'db_jacket') . '/js/jquery.image-depth.js';
}
usuario24831
fuente
0

Aunque el OP trata sobre Drupal 8, esto podría hacerse de manera similar en Drupal 7 sin usar drupal_add_js()para comenzar a acostumbrarse a no tener drupal_add_js():

/**
 * Implements hook_preprocess_page().
 */
function YOURMODULE_preprocess_page(&$variables) {
  $module_path = drupal_get_path('module', 'YOURMODULE');
  $variables['page']['content']['#attached']['js'][$module_path . '/js/YOURMODULE.js'] = array();
}

Las opciones se pueden definir en la matriz vacía, consulte https://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_add_js/7 .

lmeurs
fuente