Skip to content

Commit feb8a27

Browse files
committed
bug #866 [LiveComponent] Smarter form trait data extracting (weaverryan)
This PR was squashed before being merged into the 2.x branch. Discussion ---------- [LiveComponent] Smarter form trait data extracting | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | Tickets | Fix #864 | License | MIT Try this out `@norkunas` :). The problem was actually a tricky thing that UX autocomplete does. Thanks for reporting this so quickly. Cheers! Commits ------- 9a94a48 [LiveComponent] Smarter form trait data extracting
2 parents 2da6586 + 9a94a48 commit feb8a27

10 files changed

+61
-12
lines changed

src/LiveComponent/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
"symfony/dependency-injection": "^5.4|^6.0",
4141
"symfony/form": "^5.4|^6.0",
4242
"symfony/framework-bundle": "^5.4|^6.0",
43-
"symfony/property-info": "^5.4|^6.0",
4443
"symfony/phpunit-bridge": "^6.0",
44+
"symfony/property-info": "^5.4|^6.0",
4545
"symfony/security-csrf": "^5.4|^6.0",
4646
"symfony/twig-bundle": "^5.4|^6.0",
4747
"symfony/validator": "^5.4|^6.0",

src/LiveComponent/src/ComponentWithFormTrait.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public function initializeForm(array $data): array
9090
}
9191

9292
// set the formValues from the initial form view's data
93-
$this->formValues = $this->extractFormValues($this->getForm());
93+
$this->formValues = $this->extractFormValues($this->getForm(), $this->getFormInstance());
9494

9595
return $data;
9696
}
@@ -157,7 +157,7 @@ private function submitForm(bool $validateAll = true): void
157157

158158
// re-extract the "view" values in case the submitted data
159159
// changed the underlying data or structure of the form
160-
$this->formValues = $this->extractFormValues($this->getForm());
160+
$this->formValues = $this->extractFormValues($this->getForm(), $form);
161161

162162
// remove any validatedFields that do not exist in data anymore
163163
$this->validatedFields = LiveFormUtility::removePathsNotInData(
@@ -223,7 +223,7 @@ private function getDataModelValue(): ?string
223223
* frontend, and it's meant to equal the raw POST data that would
224224
* be sent if the form were submitted without modification.
225225
*/
226-
private function extractFormValues(FormView $formView): array
226+
private function extractFormValues(FormView $formView, FormInterface $form): array
227227
{
228228
$values = [];
229229

@@ -235,8 +235,10 @@ private function extractFormValues(FormView $formView): array
235235
// is already correct. For example, an expanded ChoiceType with
236236
// options "text" and "phone" would already have a value in the format
237237
// ["text"] (assuming "text" is checked and "phone" is not).
238-
if (!($child->vars['expanded'] ?? false) && ($child->vars['compound'] ?? false)) {
239-
$values[$name] = $this->extractFormValues($child);
238+
//
239+
$isCompound = $form->has($name) && $form->get($name)->getConfig()->getOption('compound', false);
240+
if ($isCompound && !($child->vars['expanded'] ?? false)) {
241+
$values[$name] = $this->extractFormValues($child, $form->get($name));
240242

241243
continue;
242244
}

src/LiveComponent/tests/Fixtures/Component/FormWithCollectionTypeComponent.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#[AsLiveComponent('form_with_collection_type')]
2626
class FormWithCollectionTypeComponent extends AbstractController
2727
{
28+
public bool $enableCsrf = false;
29+
2830
use ComponentWithFormTrait;
2931
use DefaultActionTrait;
3032

@@ -39,7 +41,9 @@ public function __construct()
3941

4042
protected function instantiateForm(): FormInterface
4143
{
42-
return $this->createForm(BlogPostFormType::class, $this->post);
44+
return $this->createForm(BlogPostFormType::class, $this->post, [
45+
'csrf_protection' => $this->enableCsrf,
46+
]);
4347
}
4448

4549
#[LiveAction]

src/LiveComponent/tests/Fixtures/Form/BlogPostFormType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ public function buildForm(FormBuilderInterface $builder, array $options)
3939
public function configureOptions(OptionsResolver $resolver)
4040
{
4141
$resolver->setDefaults([
42-
'csrf_protection' => false,
4342
'data_class' => BlogPost::class,
43+
'csrf_protection' => false,
4444
]);
4545
}
4646
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Symfony\UX\LiveComponent\Tests\Fixtures\Form;
4+
5+
use Symfony\Component\Form\AbstractType;
6+
use Symfony\Component\Form\Extension\Core\Type\TextType;
7+
use Symfony\Component\Form\FormBuilderInterface;
8+
use Symfony\Component\Form\FormInterface;
9+
use Symfony\Component\Form\FormView;
10+
use Symfony\Component\OptionsResolver\OptionsResolver;
11+
12+
class ComplexFieldType extends AbstractType
13+
{
14+
public function buildForm(FormBuilderInterface $builder, array $options)
15+
{
16+
$builder->add('sub_field', TextType::class);
17+
}
18+
19+
public function finishView(FormView $view, FormInterface $form, array $options)
20+
{
21+
// try to confuse ComponentWithFormTrait
22+
$view->vars['compound'] = false;
23+
}
24+
}

src/LiveComponent/tests/Fixtures/Form/FormWithManyDifferentFieldsType.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
6767
->add('checkbox_checked', CheckboxType::class)
6868
->add('file', FileType::class)
6969
->add('hidden', HiddenType::class)
70+
->add('complexType', ComplexFieldType::class)
7071
;
7172
}
7273

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
<div {{ attributes }}>
2-
{{ form(this.form) }}
2+
{{ form_start(this.form) }}
3+
{#
4+
This is a compound field, but to be tricky, we change its compound
5+
view value to false. This causes the rendering system (correctly) to
6+
choke on it. So, we render it manually. This imitates the behavior
7+
of the UX autocomplete form type.
8+
#}
9+
{{ form_row(this.form.complexType.sub_field) }}
10+
{{ form_widget(this.form) }}
11+
{{ form_end(this.form) }}
312
</div>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{{ component('form_with_collection_type', {
2+
enableCsrf: true,
3+
}) }}

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ class ComponentWithFormTest extends KernelTestCase
3535

3636
public function testFormValuesRebuildAfterFormChanges(): void
3737
{
38-
$dehydratedProps = $this->dehydrateComponent($this->mountComponent('form_with_collection_type'))->getProps();
39-
4038
$browser = $this->browser();
4139
$crawler = $browser
42-
->get('/_components/form_with_collection_type?props='.urlencode(json_encode($dehydratedProps)))
40+
->get('/render-template/render_form_with_collection_type')
4341
->crawler()
4442
;
43+
$div = $crawler->filter('[data-controller="live"]');
44+
$dehydratedProps = json_decode($div->attr('data-live-props-value'), true);
4545

4646
// mimic user typing
4747
$updatedProps = [
@@ -181,6 +181,9 @@ public function testHandleCheckboxChanges(): void
181181
'checkbox_checked' => '1',
182182
'file' => '',
183183
'hidden' => '',
184+
'complexType' => [
185+
'sub_field' => '',
186+
],
184187
], $dehydratedProps['form']);
185188

186189
$getUrl = function (array $props, array $updatedProps = null) {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ public function testFormValues(): void
4545
'checkbox_checked' => '1',
4646
'file' => '',
4747
'hidden' => '',
48+
'complexType' => [
49+
'sub_field' => '',
50+
],
4851
],
4952
$component->formValues
5053
);

0 commit comments

Comments
 (0)