4

How do I get the attachments out a twig file and add them to a build array?

If there is a twig file with

{{ attach_library('mytheme/pullquote') }}

And because it's in an ajax response, I need to get the attachments out without rendering the page, how do I get a new build array with that library attached?

In my controller:

   $build['pullquote'] = [
      '#theme' => 'pullquote',
      '#quote_text' => $quote_text,
      '#attribution_name' => $attribution_name,
      '#attribution_title' => $attribution_title,
      '#size' => $size,
    ];

    $response = new AjaxResponse();
    $response->addCommand(new EmbedInsertCommand($build));
    return $response;

Because the library is added in twig and not in the build array, it's not coming through in the response.

The EmbedInsertCommand is from the embed module, which entity_embed inherits from, at embed/src/Ajax/EmbedInsertCommand.php

which uses the CommandWithAttachedAssetsTrait, with this function:

 /**
   * Processes the content for output.
   *
   * If content is a render array, it may contain attached assets to be
   * processed.
   *
   * @return string|\Drupal\Component\Render\MarkupInterface
   *   HTML rendered content.
   */
  protected function getRenderedContent() {
    $this->attachedAssets = new AttachedAssets();
    if (is_array($this->content)) {
      $html = \Drupal::service('renderer')->renderRoot($this->content);
      $this->attachedAssets = AttachedAssets::createFromRenderArray($this->content);
      return $html;
    }
    else {
      return $this->content;
    }
  }

Unfortunately, AttachedAssets::createFromRenderArray misses libraries added within twig.

1 Answer 1

0

Usually ajax commands which add html are able to catch attachments bubbling up when they render the content. Don't know EmbedInsertCommand(). The name clearly says it is an command inserting html, so it should be able to do it.

For commands not able to handle attachments you can render the content already in the controller and add the attachments to the response here:

  $response = new AjaxResponse();
  $html = \Drupal::service('renderer')->renderRoot($build);
  $response->addCommand(new EmbedInsertCommand($html));
  $response->setAttachments($build['#attached']);
  return $response;

This is only a workaround, not the recommend way, because Ajax does some more processing of the attachments before adding them to the response, but for a single command this should be OK.

2
  • Thanks for the answer, but $build['#attached'] lacks the libraries added through twig, so I could just attach the library outside the twig to the build array, but I was hoping there was a way to render the twig enough to extract the library attached within the twig.
    – oknate
    Jul 11, 2018 at 18:56
  • 2
    renderRoot() bubbles all attachments to $build['#attached'], no matter how deep they are nested inside of $build. So if the attachment is missing already at this point then it is not an Ajax issue.
    – 4uk4
    Jul 11, 2018 at 19:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.