I'm having a very hard time figuring out how in a generic way (so not a specific display plugin, but say in a module that can only implement hooks) to add #attached information to a View's output so that it will get rendered and output. Specifically I want to add libraries to Views using ['#attached']['library'][] = array('module', 'library-name').

I see that #1748164: Use #attached to add all CSS and JS was open at one point and set to be backported to Drupal 7, but was eventually marked as a duplicate of #1811828: Use #attached to find the css/js of a view which looks like it contains D8 only changes that cannot be backported.

Am I missing some kind of hook or preprocess that I can use? Currently I have to use the following which will have compatibility problems with things like AJAX views:

function mymodule_views_pre_render($view) {
  // Add our library to all views (this is silly, but I just want to test adding a library).
  drupal_add_library('mymodule', 'mylibrary');
}

Comments

mariacha1’s picture

Issue summary: View changes
mariacha1’s picture

stewart.adam’s picture

If your View uses exposed forms, a workaround is to implement hook_form_views_exposed_form_alter() to modify $form['#attached']. One can check against $form['#id'] to identify the current view.

msypes’s picture

I'm thinking this thread is more a support request than a bug report, isn't it?
And in that vein, is there a proper method to add #attached to a view with a hook? Currently, I'm using the older, and soon-to-be-deprecated drupal_add_xxx(). Just trying to stay up to date.

plazik’s picture

I'm using this code in my_module_preprocess_views_view(&$vars):

$css['#attached']['css'][] = drupal_get_path('module', 'my_module') . '/my_module.css';
drupal_render($css);
plazik’s picture

For D8:

/**
 * Preprocess for view.
 */
function THEMENAME_preprocess_views_view(&$variables) {
  if ($variables['view']->storage->id() == 'VIEWSNAME') {
    $variables['#attached']['library'][] = 'THEMENAME/LIBRARYNAME';
  }
}

doublejosh’s picture

Using the exposed form seems like the closest approach... if you're using filters.

function mymodule_form_views_exposed_form_alter(&$form, &$form_state) {
  $my_view_forms = array(
    'views-exposed-form-myview',
    'views-exposed-form-myotherview',
  );
  if (isset($form['#id']) && in_array($form['#id'], $my_view_forms)) {
    // NOTE: JS added via form for cached rendering.
    $form['#attached']['js'][] =
      drupal_get_path('module', 'mymodule') . '/js/myscript.js';
  }
}

Another option is to use the Context Add Assets module.

sgdev’s picture

@doublejosh, thanks for the suggestion about Context Add Assets, although we're not using Context and just want to attach JavaScript to a view without exposed filters.

We decided to essentially do what Dave Reid mentioned in the original post, using drupal_add_library in a template_preprocess for the View.

taggartj’s picture

@plazik His works for modules as well for D8 as this hook works in modules.

/**
 * hook_preprocess_views_view().
 */
function MODULENAME_preprocess_views_view(&$variables) {
  if ($variables['view']->storage->id() == 'VIEWSNAME') {
    $variables['#attached']['library'][] = 'MODULENAME/LIBRARYNAME';
  }
}