Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TwigComponent] Add 'host' context when rendering embedded components #863

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/TwigComponent/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGELOG

## 2.9.0

- Add `host` context, available in embedded components

## 2.8.0

- Add new HTML syntax for rendering components: `<twig:ComponentName>`
Expand Down
3 changes: 3 additions & 0 deletions src/TwigComponent/src/ComponentRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ private function preRender(MountedComponent $mounted, array $context = []): PreR
// add the component as "this"
['this' => $component],

// add the "host" component when rendering an embedded component
isset($context[PreRenderEvent::EMBEDDED], $context['this']) && true === $context[PreRenderEvent::EMBEDDED] ? ['host' => $context['this']] : [],

// add computed properties proxy
['computed' => new ComputedPropertiesProxy($component)],

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\UX\TwigComponent\Tests\Fixtures\Component;

use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;

/**
* @author Bart Vanderstukken <[email protected]>
*/
#[AsTwigComponent('embedded_content_bar')]
final class ComponentWithEmbeddedContentBar
{
public $id;
public $propGivenThis;
public $propGivenHost;

public function getSomething()
{
return "you called Bar{$this->id}";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\UX\TwigComponent\Tests\Fixtures\Component;

use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;

/**
* @author Bart Vanderstukken <[email protected]>
*/
#[AsTwigComponent('embedded_content_foo')]
final class ComponentWithEmbeddedContentFoo
{
public function getSomething()
{
return 'you called Foo';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\UX\TwigComponent\Tests\Fixtures\Component;

use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;

/**
* @author Bart Vanderstukken <[email protected]>
*/
#[AsTwigComponent('nested_component_wrapper')]
final class NestedComponentWrapper
{
public function getSomething()
{
return 'you called wrapper';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<h1>A Bar component</h1>

propGivenHost in Bar{{ id }}: {{ propGivenHost }}
propGivenThis in Bar{{ id }}: {{ propGivenThis }}
this in Bar{{ id }}: {{ this.something }}

<div class='embedded content in Bar{{ id }}'>
{% block content %}{% endblock %}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<h1>A Foo component</h1>
<div class='embedded content in Foo'>
{% block content %}{% endblock %}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
This at root: {{ this.something }}
<twig:embedded_content_foo>
host from embedded content in Foo element: {{ host.something }}
this from embedded content in Foo element: {{ this.something }}

<twig:embedded_content_bar :propGivenThis="this.something" :propGivenHost="host.something" id='1' >
<twig:embedded_content_bar :propGivenThis="this.something" :propGivenHost="host.something" id='2' />
</twig:embedded_content_bar>
</twig:embedded_content_foo>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<twig:nested_component_wrapper />
34 changes: 34 additions & 0 deletions src/TwigComponent/tests/Integration/ComponentExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,40 @@ public function testCanRenderEmbeddedComponent(): void
$this->assertStringContainsString('custom td (1)', $output);
}

public function testCanRenderNestedEmbeddedComponentReferencingHost(): void
{
$output = self::getContainer()->get(Environment::class)->render('nested_components.html.twig');

$this->assertStringContainsString(<<<string
This at root: you called wrapper
<h1>A Foo component</h1>
<div class='embedded content in Foo'>
host from embedded content in Foo element: you called wrapper
this from embedded content in Foo element: you called Foo

<h1>A Bar component</h1>

propGivenHost in Bar1: you called wrapper
propGivenThis in Bar1: you called Foo
this in Bar1: you called Bar1

<div class='embedded content in Bar1'>
<h1>A Bar component</h1>

propGivenHost in Bar2: you called Foo
propGivenThis in Bar2: you called Bar1
this in Bar2: you called Bar2

<div class='embedded content in Bar2'>
</div>

</div>
</div>
string,
$output
);
}

public function testComponentWithNamespace(): void
{
$output = $this->renderComponent('foo:bar:baz');
Expand Down