I created the following preprocess function to add a value.

function mytheme_preprocess_node__audio(&$variables) {
  $node = $variables['node'];
  $media_field = $node->get('field_image')->entity->uri->value;
  $variables['poster'] = file_create_url($media_field);

I want to output the content of $variables['poster'] in the file-audio.html.twig template.

<audio {{ attributes }} poster="{{ poster }}">
  {% for file in files %}
    <source {{ file.source_attributes }} />
  {% endfor %}

{{ poster }} outputs an empty string. I have tried multiple methods, with no success.

I can get the variable in the field template (field--field-audio.html.twig), but it is not available to the child file template I am using.

How do I get the value of $variables['poster'] in the template file I am using?

  • mytheme_preprocess_node__audio() is a node preprocess function. If file-audio.html.twig is not a node template file used for the same content type, what set in mytheme_preprocess_node__audio() will not be available in file-audio.html.twig. From the question is not clear for what the file-audio.html.twig template is used.
    – apaderno
    Apr 1 '20 at 13:54
  • Thanks kiamlaluno, i've tried preprocessing other scopes but I need a different field from the field that I am working on (trying to join two fields data together) so I'm not sure what the scope should be - what I should be preporcessing? The file-audio.html.twig is a child twig template for the audio field and I can't figure out the scope to get a variable into it...
    – dave t
    Apr 1 '20 at 21:49

So I figured this out, it was not straightforward or obvious, and I could find no forum or post detailing this method, so hopefully it helps others. The preprocess function changes to preprocess field as:

function MYTHEME_preprocess_field(array &$variables, $hook) {
  $element = $variables['element'];

  switch ($element['#field_name']) {
    // Machine name of the field
    case 'field_audio':
      $node = \Drupal::request()->attributes->get('node');
      // separate field (machine name = field_image) that holds image for poster
      $media_field = $node->get('field_image')->entity->uri->value; 
      $variables['poster'] = file_create_url($media_field);

Then in the field twig file (field--field-audio.html.twig), replace the appropriate item.content section (or all of them as I did, just in case!)

      {% set attr = item.content['#attributes']|merge({'poster': poster}) %}
      {% set mycontent = item.content|merge({'#attributes': attr}) %}

      <div{{ attributes.addClass(classes, 'field--item') }}> {{ mycontent }} </div>

Finally in the file-audio.html.twig template you just need to add the poster="{{poster}}" like:

<audio {{ attributes }} style="background: transparent url({{ attributes.poster }});">

I've done the same for Video, i.e. using a separate field for the poster of the html5 video tag, using the same method EXCEPT in the field template #attributes is #player_attributes as you should be able to see in the file twig template, named video-player-formatter.html.twig in my case. Happy to post the code if anyone needs it.

Thanks to the drupal forums, twig documentation and of course stackexchange for the snippets I picked up along the way to figure this out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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