3

I'd like to use Twig Tweak's drupal_view() to render a view in my paragraph template. I have a couple entity reference fields on the paragraph and need the IDs of the referenced entities passed as contextual filter arguments.

I built a Contextual Filter String field formatter to format the contextual filter string with the hope that it could be passed directly as the argument's value. The formatter will return all if the reference field is empty, otherwise it will return the referenced entity IDs as a string with AND/OR separators, e.g. 1,2,3 for AND or 1+2+3 for OR.

Inside my template, I'm attempting to render the view with the following twig:

{% set arg1 = content.field_arg1|render %}
{% set arg2 = content.field_arg2|render %}

{{ drupal_view('my_view', 'my_display', arg1, arg2) }}

But this does not work!

Rather than strings, my arg variables are actually Drupal\Core\Render\Markup objects so the arguments are not passed correctly to the view.

After researching, I've found that I can workaround this issue by filtering my arg variables with a php filter that returns a string. For example, using the trim filter works:

{% set arg1 = content.field_arg1|render|trim %}
{% set arg2 = content.field_arg2|render|trim %}

{{ drupal_view('my_view', 'my_display', arg1, arg2) }}

If possible, I would like to build a render array that doesn't require any fancy footwork in the template to pass the values to the drupal_view() function. I.e. a render array where I can pass content.field_arg1 or content.field_arg|render directly as the arguments. Is this possible?

Render arrays I've tried that did not work:

$inline_template = [
  '#type' => 'inline_template',
  '#template' => '{{ contextual_filter_string }}', // also tried with |trim filter here
  '#context' => [
    'contextual_filter_string' => '1+2+3',
  ],
];

$markup = [
  '#markup' => '1+2+3',
];

$plain_text = [
  '#plain_text' => '1+2+3',
];

Note: not shown in the above render arrays is cache metadata (tags) for the entities referenced in the field.

Yes, there are alternate ways to get these field values and pass them to drupal_view(), however that's not what this question is about. I would like to use a Field Formatter to return a render array (I think I have to return a render array) that results in a string ready to be passed directly to drupal_view(). This allows me to configure the format of the argument in the UI without touching code. I suspect this is impossible.

Some alternative approaches that I've considered:

  • I could preprocess my paragraph and add these filter strings to the $variables array.
  • I could build my own twig function to generate these contextual filter strings.
  • I could get the values directly from the entity in my template, e.g. paragraph.field_arg1.target_id as Les Lim answered, but this doesn't work cleanly for multi-value fields.

Edit: It seems that this is impossible so accepting Les Lim's answer as the best alternative.

4
  • 3
    For PHP see drupal.stackexchange.com/questions/207699/…. If you use the current Drupal Twig version 2.14 this is also possible in Twig. See twig.symfony.com/doc/2.x/filters/column.html
    – 4k4
    Aug 10 at 16:13
  • 2
    I edited my answer, and then refreshed to see your addendum to the question at the bottom. I'm not sure I have a direct answer for you; I think what you're discovering is that the field formatter system wasn't designed to be used in the way that you're trying to use it. It assumes that it should be returning filtered/escaped HTML markup, not raw unescaped strings that you'd want to use as a View argument.
    – Les Lim
    Aug 10 at 16:18
  • 2
    @LesLim - Yes, thank you, that's my impression too. I really wanted the formatter to work cleanly because it would make it so easy to configure and reuse without much PHP or Twig knowledge. Your edits are helpful, even though it ultimately does not answer my question.
    – sonfd
    Aug 10 at 16:27
  • @4k4 Thanks for the tip about Twig's column filter! I edited my answer again.
    – Les Lim
    Aug 10 at 16:29
7

Original response, assuming you only need a single value from each field:

Instead of using the rendered field output that you get with items in the {{ content }} array, you should probably use raw values directly from the entity. Raw values are much more likely to be what your Views arguments are looking for in the first place.

In Drupal 8/9, if the raw entity is available to the Twig template (and it is for Paragraph templates), you can use Entity API notation to get exact raw values from your entity:

{% set arg1 = paragraph.field_arg1.target_id %}
{% set arg2 = paragraph.field_arg2.target_id %}

Addendum, for needing multiple raw field values joined together

After re-reading the question, I realize you need all the raw values from a field joined together with a string. The contrib module Twig Field Value gives you handy generic tools for exactly this purpose. In this case, you would use its field_raw filter:

{% set arg1 = content.field_arg1|field_raw('target_id')|safe_join('+') %}
{% set arg2 = content.field_arg2|field_raw('target_id')|safe_join(',') %}

Edit: Join multiple raw field values without Twig Field Value (thanks 4k4 for the tip)

You don't actually need Twig Field Value to get the target_id values from a multiple-value field - you can extract multiple values from a raw entity field using Twig's built-in column filter.

{% set arg1 = paragraph.field_arg1|column('target_id')|safe_join('+') %}
{% set arg2 = paragraph.field_arg2|column('target_id')|safe_join(',') %}
1
  • 2
    Throw a |default('all') at the end and you can even get all as a value if the field is empty.
    – sonfd
    Aug 10 at 16:29

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.