Repository: symfony/ux
Pull request #2847 (2025-06-19 10:28:47)

[Doc] Update the docs about nested Twig components
| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no
| Docs?         | yes
| Issues        | -
| License       | MIT

This morning I had some issues related to nested components. I searched for "nested" in the docs, so I missed all the explanations about `outerScope`, etc. that are included in another section.

I propose to mention all that in the "Nested Components" section but without repeating the actual explanations, just as a quick recap.


Patch:
diff --git a/.github/workflows/code-quality.yaml b/.github/workflows/code-quality.yaml
index 4ce75fba..08e83634 100644
--- a/.github/workflows/code-quality.yaml
+++ b/.github/workflows/code-quality.yaml
@@ -46,18 +46,17 @@ jobs:
         strategy:
             fail-fast: false
             matrix:
-                php-version: ['8.1']
+                php-version: [ '8.1', '8.2', '8.3', '8.4']
                 dependency-version: ['']
                 symfony-version: ['']
                 minimum-stability: ['stable']
                 include:
-                    # dev packages (probably not needed to have multiple such jobs)
-                    - minimum-stability: 'dev'
-                      php-version: 8.4
                     # lowest deps
-                    - dependency-version: 'lowest'
+                    -   php-version: '8.1'
+                        dependency-version: 'lowest'
                     # LTS version of Symfony
-                    - symfony-version: '6.4.*'
+                    -   php-version: '8.1'
+                        symfony-version: '6.4.*'
         steps:
             -   name: Checkout
                 uses: actions/checkout@v4
@@ -79,7 +78,7 @@ jobs:
             -   name: Setup PHP
                 uses: shivammathur/setup-php@v2
                 with:
-                    php-version: 8.1
+                    php-version: ${{ matrix.php-version }}
                     tools: flex
 
             - name: Install root dependencies
diff --git a/src/TwigComponent/doc/index.rst b/src/TwigComponent/doc/index.rst
index de3cb4e2..1161f385 100644
--- a/src/TwigComponent/doc/index.rst
+++ b/src/TwigComponent/doc/index.rst
@@ -738,6 +738,8 @@ There is also a non-HTML syntax that can be used:
         {% block footer %}... footer content{% endblock %}
     {% endcomponent %}
 
+.. _embedded-components-context:
+
 Context / Variables Inside of Blocks
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -801,10 +803,7 @@ When overriding the ``alert_message`` block, you have access to the ``message``
         </twig:block>
     </twig:SuccessAlert>
 
-.. versionadded:: 2.13
-
-    The ability to refer to the scope of higher components via the ``outerScope``
-    variable was added in 2.13.
+.. _embedded-components-outerScope:
 
 As mentioned before, variables from lower components are merged with those from
 upper components. When you need access to some properties or functions from higher
@@ -825,6 +824,11 @@ components, that can be done via the ``outerScope...`` variable:
         {{ outerScope.this.someProp }} {# references a "someProp" prop from SuccessAlert #}
     {% endcomponent %}
 
+.. versionadded:: 2.13
+
+    The ability to refer to the scope of higher components via the ``outerScope``
+    variable was added in 2.13.
+
 You can keep referring to components higher up as well. Just add another ``outerScope``.
 Remember though that the ``outerScope`` reference only starts once you're INSIDE the (embedded) component.
 
@@ -842,6 +846,8 @@ Remember though that the ``outerScope`` reference only starts once you're INSIDE
         {% endblock %}
     {% endcomponent %}
 
+.. _embedded-components-outerBlocks:
+
 Inheritance & Forwarding "Outer Blocks"
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -1563,9 +1569,33 @@ listen to ``PreMountEvent`` or ``PostMountEvent``.
 Nested Components
 -----------------
 
-It's totally possible to include components as part of the contents of another
-component. When you do this, all components render independently. The only
-caveat is that you cannot mix the Twig syntax and the :ref:`HTML syntax <component_html_syntax>`
+It's possible to include components inside another component:
+
+.. code-block:: html+twig
+
+    <twig:SomeComponent>
+        {% for i in 1..10 %}
+            <twig:AnotherComponent>
+                {{ i }}
+            </twig:AnotherComponent>
+        {% endfor %}
+    </twig:SomeComponent>
+
+When you do this, each component is rendered independently, but there are some
+important caveats:
+
+#. As :ref:`explained above <embedded-components-context>`, the variables of a
+   component are merged with the variables of its parent component. Variables
+   with the same name (e.g. ``this`` or ``computed``) are overridden by the
+   inner component;
+#. The original parent component variables are available via the special
+   :ref:`outerScope variable <embedded-components-outerScope>`, so you can, for
+   example, call ``outerScope.this.someFunction()``;
+#. The contents of blocks defined in parent components are available via the
+   special :ref:`outerBlocks variable <embedded-components-outerBlocks>`, so you
+   can call ``block(outerBlocks.someBlockName)``.
+
+Finally, you cannot mix the Twig syntax and the :ref:`HTML syntax <component_html_syntax>`
 when using nested components:
 
 .. code-block:: html+twig
@@ -1599,8 +1629,9 @@ when using nested components:
         {% endblock %}
     {% endcomponent %}
 
-If you're using `Live Components`_, then there *are* some guidelines related to
-how the re-rendering of parent and child components works. Read `Live Nested Components`_.
+If you're using `Live Components`_, there *are* additional guidelines related
+to how parent and child components are re-rendered. See `Live Nested Components`_
+for details.
 
 Configuration
 -------------


Test patch:
diff --git a/src/Autocomplete/tests/Fixtures/Kernel.php b/src/Autocomplete/tests/Fixtures/Kernel.php
index 7fc8adcf..de2877b0 100644
--- a/src/Autocomplete/tests/Fixtures/Kernel.php
+++ b/src/Autocomplete/tests/Fixtures/Kernel.php
@@ -11,7 +11,6 @@
 
 namespace Symfony\UX\Autocomplete\Tests\Fixtures;
 
-use Composer\InstalledVersions;
 use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
 use Doctrine\ORM\Mapping\AssociationMapping;
 use Fixtures\Form\CategoryWithCallbackAsCustomValue;
@@ -105,7 +104,7 @@ final class Kernel extends BaseKernel
             'auto_refresh_proxies' => false,
         ]);
 
-        $doctrineConfig = [
+        $config = [
             'dbal' => ['url' => '%env(resolve:DATABASE_URL)%'],
             'orm' => [
                 'auto_generate_proxy_classes' => true,
@@ -123,17 +122,11 @@ final class Kernel extends BaseKernel
         ];
         if (class_exists(AssociationMapping::class)) {
             // Doctrine ORM >= 3.0
-            $doctrineConfig['orm']['controller_resolver'] = [
+            $config['orm']['controller_resolver'] = [
                 'auto_mapping' => true,
             ];
         }
-        if (null !== $doctrineBundleVersion = InstalledVersions::getVersion('doctrine/doctrine-bundle')) {
-            if (\PHP_VERSION_ID >= 80400 && version_compare($doctrineBundleVersion, '2.15.0', '>=')) {
-                $doctrineConfig['orm']['enable_native_lazy_objects'] = true;
-            }
-        }
-
-        $c->extension('doctrine', $doctrineConfig);
+        $c->extension('doctrine', $config);
 
         $c->extension('security', [
             'password_hashers' => [
diff --git a/src/LiveComponent/tests/Fixtures/Kernel.php b/src/LiveComponent/tests/Fixtures/Kernel.php
index 4b0cd90d..508dd242 100644
--- a/src/LiveComponent/tests/Fixtures/Kernel.php
+++ b/src/LiveComponent/tests/Fixtures/Kernel.php
@@ -186,9 +186,6 @@ final class Kernel extends BaseKernel
             if (version_compare($doctrineBundleVersion, '2.12.0', '>=')) {
                 $doctrineConfig['orm']['controller_resolver']['auto_mapping'] = false;
             }
-            if (\PHP_VERSION_ID >= 80400 && version_compare($doctrineBundleVersion, '2.15.0', '>=')) {
-                $doctrineConfig['orm']['enable_native_lazy_objects'] = true;
-            }
         }
 
         $c->extension('doctrine', $doctrineConfig);