Support from Acquia helps fund testing for Drupal Acquia logo

Comments

lauriii created an issue. See original summary.

lauriii’s picture

Status: Active » Needs review
FileSize
5.76 KB
lauriii’s picture

The syntax to try this is:

 {%
    theme "item_list" with {
      items: [
        'Test',
        'Test2'
      ],
    }
 %}
joelpittet’s picture

This is awesome and RTBC other than these nitpicks

  1. +++ b/src/Template/TwigExtension.php
    @@ -0,0 +1,94 @@
    +namespace Drupal\components\Template;
    +use Drupal\Core\Render\RendererInterface;
    

    \n after namespace.

  2. +++ b/src/Template/TwigExtension.php
    @@ -0,0 +1,94 @@
    +    return "components";
    

    single quotes

  3. +++ b/src/Template/TwigNodeTheme.php
    @@ -0,0 +1,47 @@
    +  public function __construct(\Twig_Node_Expression $theme, \Twig_Node_Expression $variables = null, $ignore_missing = false, $lineno, $tag = null) {
    

    /false/FALSE/ and /null/NULL/

  4. +++ b/src/Template/TwigNodeTheme.php
    @@ -0,0 +1,47 @@
    +      array('theme' => $theme, 'variables' => $variables),
    +      array('ignore_missing' => (bool) $ignore_missing),
    

    short array

  5. +++ b/src/Template/TwigNodeTheme.php
    @@ -0,0 +1,47 @@
    +    if ($this->getAttribute('ignore_missing')) {
    +      $compiler->outdent()
    +        ->write("} catch (Twig_Error_Loader \$e) {\n")
    +        ->indent()
    

    Probably don't need this feature now.

  6. +++ b/src/Template/TwigThemeTokenParser.php
    @@ -0,0 +1,61 @@
    + *      'items: [],
    

    missing single quote after 'items'

lauriii’s picture

Thanks for the review @joelpittet!

Fabianx’s picture

+++ b/src/Template/TwigNodeTheme.php
@@ -0,0 +1,47 @@
+    $compiler->write('echo ')
+      ->subcompile(new \Twig_Node_Expression_Function('theme', new \Twig_Node([$this->getNode('theme'), $this->getNode('variables')]), $this->getLine()))
+      ->raw("; \n");

It might be better to use a Twig_Node_Print unless we are 100% sure that we do not want to pass this through auto-escape, which might be true.

Nice work! - Looks great!

lauriii’s picture

Very good point @Fabianx! Even though our current render system always returns safe markup, it might not be always the case if someone is using custom renderer / modified twig extension. Better to be safe than sorry!

Fabianx’s picture

Status: Needs review » Reviewed & tested by the community

RTBC - Looks good to me then! :)

  • JohnAlbin committed bc12562 on 8.x-1.x authored by lauriii
    Issue #2821512 by lauriii, Fabianx, joelpittet: Render array generator
    
JohnAlbin’s picture

I looked at this patch very carefully, and this looks like a fancy way to do a Twig include, right?

In vanilla Twig, you can use a theme hook's template with:

{% include "@THEMENAME/item_list.html.twig" with {
      items: [
        'Test',
        'Test2'
      ],
    }
 %}

But you can't use a Drupal theme hook suggestion (e.g. item_list__node) and none of the preprocess hooks or template suggestion hooks are called.

Using a suggestion in theme would work, right?

{%
    theme "item_list__node" with {
      items: [
        'Test',
        'Test2'
      ],
    }
%}

Are there any other reasons to use theme over include? Include would be faster if you don't need those Drupal-specific features.

We need some docs.

And we need some tests!

But I've committed this patch in the meantime. Really good work!

JohnAlbin’s picture

Status: Reviewed & tested by the community » Needs work
lauriii’s picture

Thank you for the commit @JohnAlbin!

I looked at this patch very carefully, and this looks like a fancy way to do a Twig include, right?

Exactly! This way we can get the best parts of the theme system in use; such as documented variables in the theme hooks, preprocess functions for actual data preprocessing and a way to do overrides in child themes. Maybe in future even modules could work the same way so that they provide components and you could just override a component inside your theme. And if you need to change something on the data, you would also override the connector template.

Include would be faster if you don't need those Drupal-specific features.

Most people don't have to care about most of Drupal's features even though they are available. This would be just a way to scale this model to become slightly more flexible so that we could potentially introduce this workflow in core!

We need some docs.
And we need some tests!

I agree with both!

kevinquillen’s picture

Whats the status on this patch? I think still allowing for override while supporting include like functionality is a great addition.

dionsj’s picture

Would using the theme call, does it also retain the caching metadata (from #cache render array)?
The reason I ask is that we've recently started encountering this issue:
Allow explicit bubbling of cacheability metadata inside Twig template (when accessing data from instead of rendering render arrays)

Another question, the theme looks similar to twigs include, but wouldn't it then also make sense to have one that works similar to twigs embed, so that we can override twig blocks within the embed?

JohnAlbin’s picture

Version: 8.x-1.x-dev » 8.x-2.x-dev
JohnAlbin’s picture

I'm thinking of changing how the theme() function works. (Not how the theme tag works.)

#3082816: Make theme() function return render array could use some reviews.

JohnAlbin’s picture

I created a bunch of child issues with justifications for each change I wanted to make to this work. They are all completed now.

  1. The theme tag has been removed because it is unsemantic. See #3090458: Remove theme tag
  2. The theme() function returns a render array because core already renders array printed with {{ }}. And we can now apply filters to the raw render array (including the render filter if you really want a string). See #3082816: Make theme() function return render array
  3. The theme() function has properly named arguments now. See #3090506: Improve named arguments of theme function

This is how the function works now:

{{ theme("card", {
    title: label,
    text: body,
  }
) }}

With Twig's new named arguments, you could also call that function like this:

{{ theme(
  hook = "card",
  variables = {
    title: label,
    text: body,
  }
) }}

Or like this:

{{ theme("card",
  variables = {
    title: label,
    text: body,
  }
) }}

I also kick-started the discussion in the core issue today by posting a patch, so if we want to discuss implementation details, it's probably best to do that there: #2818121: Create alternative to Twig include function to improve Drupal integration

JohnAlbin’s picture

JohnAlbin’s picture

Title: Render array generator » Create alternative to Twig include function to improve Drupal integration

Updated title to match core issue.

JohnAlbin’s picture

With #3091827: Use variadic arguments for template function and #3091775: Rename theme Twig function to be called 'template()', the latest version of this is now:

{{
  template("item-list.html.twig",
    title = "Animals not yet in Drupal core"
    items = ["lemur", "weasel", "honey badger"],
  )
}}

The template() function also accepts as its first argument: "item-list" or "item_list" or "item_list__node".

Fabianx’s picture

I think this can be closed now again or is there more to do?

JohnAlbin’s picture

Status: Needs work » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.