symfony / ux

Symfony UX initiative: a JavaScript ecosystem for Symfony
https://ux.symfony.com/
MIT License
824 stars 298 forks source link

Twig-components see different _context when rendered with <twig:Test></twig:Test> instead of <twig:Test/> #1926

Closed gewait closed 3 months ago

gewait commented 3 months ago

Twig-components see different _context when rendered with <twig:Test></twig:Test> instead of <twig:Test/>

Template variables passed from controller to template are only visible inside the twig-component when the twig-component is rendered with opening and closing tag.

Is this the normal and expected behavior?

What am I doing wrong?

Could this possibly be a bug?


Environment: Current standard skeleton created with

symfony new projectname --webapp

Symfony 7.1 "symfony/ux-twig-component": "^2.18"

See screenshot and reproducer project.


Controller:

    #[Route('/', name: 'app_test')]
    public function index(): Response
    {
        return $this->render('test/index.html.twig', [
            'controller_name' => 'TestController',
            '_______test_variable_from_controller' => '*****CAN YOU SEE ME???????******',
            'syntax1' => '<twig:Test></twig:Test>',
            'syntax2' => '<twig:Test/>',
        ]);
    }

Template:

{% extends 'base.html.twig' %}

{% block body %}

    <p>look for "*****CAN YOU SEE ME???????******" inside of the following dumps.</p>

    <p>dump of _context in template</p>
    <p>variable is visible</p>
    {{ dump({'templates/test/index.html.twig': _context}) }}

    <p>dump of _context inside of the component, when the component is integrated into the template with syntax "{{ syntax1 }}"</p>
    <p>variable is visible</p>
    {# when using this syntax the component DOES SEE the variables passed from the controller #}
    <twig:Test></twig:Test>

    <p>dump of _context inside of the component, when the component is integrated into the template with syntax  "{{ syntax2 }}"</p>
    <p>variable is NOT VISIBLE</p>
    {# when using this syntax the component DOES NOT SEE the variables passed from the controller #}
    <twig:Test/>
{% endblock %}

Twig-Component:

<div{{ attributes }}>
    <!-- component html -->
    {{ dump({'templates/components/Test.html.twig': _context}) }}
</div>

Screenshot:

reproducer-screenshot3


Reproducer:

twig-component-reproducer.zip

smnandre commented 3 months ago

<twig:Test></twig:Test> is more or less equivalent to a Twig embed.

It should be used to pass content into a block of your Test component.

# Calling template
<twig:Test>
Like that
</twig:Test>

# Component template
<div{{ attributes }}>
 ...
{% block content %}{% endblock %}
...
</div>

<twig:Test /> is similar to a Twig function, and so work in a isolated scope.

So yes they do not work in the same way. Moreover, i think you only obtain this behaviour because you did not pass block to embed (or.. to be more precise, you should not expect sharing context with the calling context in your component template, this is more a side effect than some real feature :) )

gewait commented 3 months ago

Ah ok, thank you :). So that's a really subtle detail one just has to be aware of I guess.

The Documentation in https://symfony.com/bundles/ux-twig-component/current/index.html#context-variables-inside-of-blocks states "Conveniently, in addition to the variables from the Alert component, you also have access to whatever variables are available in the original template:", but perhaps I will have to read more carefully.

The Problem is, that for the thing I am working on right now i would like to use this "side effect". i would like to see a special variable from the controller inside some twig-component without having to manually transport it there :) if that makes sense...

Do you think it is a "reliable" side effect if I stick to the opening/closing tag syntax :-) ?

smnandre commented 3 months ago

I won't recommand it.

The documentation you mentionned is related to blocks.

So from the calling template, you can include a component and write inside its block using the current context.

But from the template of a component, you shoud never have knowledge of who is calling, or what the context is.

gewait commented 3 months ago

Ok, thank you for clarifying and for responding so quickly :+1:

smnandre commented 3 months ago

You’re welcome!