Skip to content

Commit 1da33c5

Browse files
committed
add MountedComponent object
1 parent ae73e5a commit 1da33c5

File tree

13 files changed

+152
-105
lines changed

13 files changed

+152
-105
lines changed

src/LiveComponent/src/EventListener/AddLiveAttributesSubscriber.php

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
use Symfony\Contracts\Service\ServiceSubscriberInterface;
1010
use Symfony\UX\LiveComponent\LiveComponentHydrator;
1111
use Symfony\UX\TwigComponent\ComponentAttributes;
12-
use Symfony\UX\TwigComponent\ComponentMetadata;
1312
use Symfony\UX\TwigComponent\EventListener\PreRenderEvent;
13+
use Symfony\UX\TwigComponent\MountedComponent;
1414
use Twig\Environment;
1515

1616
/**
@@ -29,7 +29,7 @@ public function onPreRender(PreRenderEvent $event): void
2929
return;
3030
}
3131

32-
$attributes = $this->getLiveAttributes($event->getComponent(), $event->getMetadata());
32+
$attributes = $this->getLiveAttributes($event->getMountedComponent());
3333
$variables = $event->getVariables();
3434

3535
if (isset($variables['attributes']) && $variables['attributes'] instanceof ComponentAttributes) {
@@ -57,12 +57,11 @@ public static function getSubscribedServices(): array
5757
];
5858
}
5959

60-
private function getLiveAttributes(object $component, ComponentMetadata $metadata): ComponentAttributes
60+
private function getLiveAttributes(MountedComponent $mounted): ComponentAttributes
6161
{
62-
$url = $this->container->get(UrlGeneratorInterface::class)
63-
->generate('live_component', ['component' => $metadata->getName()])
64-
;
65-
$data = $this->container->get(LiveComponentHydrator::class)->dehydrate($component);
62+
$name = $mounted->getMetadata()->getName();
63+
$url = $this->container->get(UrlGeneratorInterface::class)->generate('live_component', ['component' => $name]);
64+
$data = $this->container->get(LiveComponentHydrator::class)->dehydrate($mounted);
6665
$twig = $this->container->get(Environment::class);
6766

6867
$attributes = [
@@ -73,7 +72,7 @@ private function getLiveAttributes(object $component, ComponentMetadata $metadat
7372

7473
if ($this->container->has(CsrfTokenManagerInterface::class)) {
7574
$attributes['data-live-csrf-value'] = $this->container->get(CsrfTokenManagerInterface::class)
76-
->getToken($metadata->getName())->getValue()
75+
->getToken($name)->getValue()
7776
;
7877
}
7978

src/LiveComponent/src/EventListener/LiveComponentSubscriber.php

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use Symfony\UX\TwigComponent\ComponentFactory;
3434
use Symfony\UX\TwigComponent\ComponentMetadata;
3535
use Symfony\UX\TwigComponent\ComponentRenderer;
36+
use Symfony\UX\TwigComponent\MountedComponent;
3637

3738
/**
3839
* @author Kevin Bond <[email protected]>
@@ -144,9 +145,13 @@ public function onKernelController(ControllerEvent $event): void
144145
throw new NotFoundHttpException(sprintf('The action "%s" either doesn\'t exist or is not allowed in "%s". Make sure it exist and has the LiveAction attribute above it.', $action, \get_class($component)));
145146
}
146147

147-
$this->container->get(LiveComponentHydrator::class)->hydrate($component, $data);
148+
$mounted = $this->container->get(LiveComponentHydrator::class)->hydrate(
149+
$component,
150+
$data,
151+
$request->attributes->get('_component_metadata')
152+
);
148153

149-
$request->attributes->set('_component', $component);
154+
$request->attributes->set('_mounted_component', $mounted);
150155

151156
if (!\is_string($queryString = $request->query->get('args'))) {
152157
return;
@@ -170,7 +175,7 @@ public function onKernelView(ViewEvent $event): void
170175
return;
171176
}
172177

173-
$response = $this->createResponse($request->attributes->get('_component'), $request);
178+
$response = $this->createResponse($request->attributes->get('_mounted_component'), $request);
174179

175180
$event->setResponse($response);
176181
}
@@ -187,14 +192,14 @@ public function onKernelException(ExceptionEvent $event): void
187192
return;
188193
}
189194

190-
$component = $request->attributes->get('_component');
195+
$mounted = $request->attributes->get('_mounted_component');
191196

192197
// in case the exception was too early somehow
193-
if (!$component) {
198+
if (!$mounted) {
194199
return;
195200
}
196201

197-
$response = $this->createResponse($component, $request);
202+
$response = $this->createResponse($mounted, $request);
198203
$event->setResponse($response);
199204
}
200205

@@ -232,15 +237,16 @@ public static function getSubscribedEvents(): array
232237
];
233238
}
234239

235-
private function createResponse(object $component, Request $request): Response
240+
private function createResponse(MountedComponent $mounted, Request $request): Response
236241
{
242+
$component = $mounted->getComponent();
243+
237244
foreach (AsLiveComponent::beforeReRenderMethods($component) as $method) {
238245
$component->{$method->name}();
239246
}
240247

241248
$html = $this->container->get(ComponentRenderer::class)->render(
242-
$component,
243-
$request->attributes->get('_component_metadata')
249+
$mounted,
244250
);
245251

246252
return new Response($html);

src/LiveComponent/src/LiveComponentHydrator.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
1818
use Symfony\UX\LiveComponent\Attribute\LivePropContext;
1919
use Symfony\UX\LiveComponent\Exception\UnsupportedHydrationException;
20+
use Symfony\UX\TwigComponent\ComponentMetadata;
21+
use Symfony\UX\TwigComponent\MountedComponent;
2022

2123
/**
2224
* @author Kevin Bond <[email protected]>
@@ -45,8 +47,10 @@ public function __construct(iterable $propertyHydrators, PropertyAccessorInterfa
4547
$this->secret = $secret;
4648
}
4749

48-
public function dehydrate(object $component): array
50+
public function dehydrate(MountedComponent $mounted): array
4951
{
52+
$component = $mounted->getComponent();
53+
5054
foreach (AsLiveComponent::preDehydrateMethods($component) as $method) {
5155
$component->{$method->name}();
5256
}
@@ -105,7 +109,7 @@ public function dehydrate(object $component): array
105109
return $data;
106110
}
107111

108-
public function hydrate(object $component, array $data): void
112+
public function hydrate(object $component, array $data, ComponentMetadata $metadata): MountedComponent
109113
{
110114
$readonlyProperties = [];
111115

@@ -187,6 +191,8 @@ public function hydrate(object $component, array $data): void
187191
foreach (AsLiveComponent::postHydrateMethods($component) as $method) {
188192
$component->{$method->name}();
189193
}
194+
195+
return new MountedComponent($component, $metadata);
190196
}
191197

192198
private function computeChecksum(array $data, array $readonlyProperties): string

src/LiveComponent/src/Twig/LiveComponentRuntime.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ public function __construct(
3131

3232
public function getComponentUrl(string $name, array $props = []): string
3333
{
34-
$component = $this->factory->create($name, $props);
35-
$params = ['component' => $name] + $this->hydrator->dehydrate($component);
34+
$mounted = $this->factory->create($name, $props);
35+
$params = ['component' => $name] + $this->hydrator->dehydrate($mounted);
3636

3737
return $this->urlGenerator->generate('live_component', $params);
3838
}

src/LiveComponent/tests/Functional/EventListener/LiveComponentSubscriberTest.php

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@
1414
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
1515
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
1616
use Symfony\UX\LiveComponent\LiveComponentHydrator;
17-
use Symfony\UX\LiveComponent\Tests\Fixtures\Component\Component1;
18-
use Symfony\UX\LiveComponent\Tests\Fixtures\Component\Component2;
19-
use Symfony\UX\LiveComponent\Tests\Fixtures\Component\Component6;
2017
use Symfony\UX\LiveComponent\Tests\Fixtures\Entity\Entity1;
2118
use Symfony\UX\TwigComponent\ComponentFactory;
2219
use Zenstruck\Browser\Response\HtmlResponse;
@@ -42,7 +39,6 @@ public function testCanRenderComponentAsHtml(): void
4239
/** @var ComponentFactory $factory */
4340
$factory = self::getContainer()->get('ux.twig_component.component_factory');
4441

45-
/** @var Component1 $component */
4642
$component = $factory->create('component1', [
4743
'prop1' => $entity = create(Entity1::class)->object(),
4844
'prop2' => $date = new \DateTime('2021-03-05 9:23'),
@@ -72,10 +68,7 @@ public function testCanExecuteComponentAction(): void
7268
/** @var ComponentFactory $factory */
7369
$factory = self::getContainer()->get('ux.twig_component.component_factory');
7470

75-
/** @var Component2 $component */
76-
$component = $factory->create('component2');
77-
78-
$dehydrated = $hydrator->dehydrate($component);
71+
$dehydrated = $hydrator->dehydrate($factory->create('component2'));
7972
$token = null;
8073

8174
$this->browser()
@@ -160,10 +153,7 @@ public function testBeforeReRenderHookOnlyExecutedDuringAjax(): void
160153
/** @var ComponentFactory $factory */
161154
$factory = self::getContainer()->get('ux.twig_component.component_factory');
162155

163-
/** @var Component2 $component */
164-
$component = $factory->create('component2');
165-
166-
$dehydrated = $hydrator->dehydrate($component);
156+
$dehydrated = $hydrator->dehydrate($factory->create('component2'));
167157

168158
$this->browser()
169159
->visit('/render-template/template1')
@@ -183,10 +173,7 @@ public function testCanRedirectFromComponentAction(): void
183173
/** @var ComponentFactory $factory */
184174
$factory = self::getContainer()->get('ux.twig_component.component_factory');
185175

186-
/** @var Component2 $component */
187-
$component = $factory->create('component2');
188-
189-
$dehydrated = $hydrator->dehydrate($component);
176+
$dehydrated = $hydrator->dehydrate($factory->create('component2'));
190177
$token = null;
191178

192179
$this->browser()
@@ -226,10 +213,7 @@ public function testInjectsLiveArgs(): void
226213
/** @var ComponentFactory $factory */
227214
$factory = self::getContainer()->get('ux.twig_component.component_factory');
228215

229-
/** @var Component6 $component */
230-
$component = $factory->create('component6');
231-
232-
$dehydrated = $hydrator->dehydrate($component);
216+
$dehydrated = $hydrator->dehydrate($factory->create('component6'));
233217
$token = null;
234218

235219
$argsQueryParams = http_build_query(['args' => http_build_query(['arg1' => 'hello', 'arg2' => 666, 'custom' => '33.3'])]);

src/LiveComponent/tests/Functional/Form/ComponentWithFormTest.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,18 @@ public function testFormRemembersValidationFromInitialForm(): void
123123

124124
$form = $formFactory->create(BlogPostFormType::class);
125125
$form->submit(['title' => '', 'content' => '']);
126-
/** @var FormWithCollectionTypeComponent $component */
127-
$component = $factory->create('form_with_collection_type', [
126+
127+
$mounted = $factory->create('form_with_collection_type', [
128128
'form' => $form->createView(),
129129
]);
130130

131+
/** @var FormWithCollectionTypeComponent $component */
132+
$component = $mounted->getComponent();
133+
131134
// component should recognize that it is already submitted
132135
$this->assertTrue($component->isValidated);
133136

134-
$dehydrated = $hydrator->dehydrate($component);
137+
$dehydrated = $hydrator->dehydrate($mounted);
135138
$dehydrated['blog_post_form']['content'] = 'changed description';
136139
$dehydrated['validatedFields'][] = 'blog_post_form.content';
137140

0 commit comments

Comments
 (0)