Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2cad8ee

Browse files
add keepAsList option to ResizeFormListener
1 parent f75a3a2 commit 2cad8ee

File tree

3 files changed

+84
-20
lines changed

3 files changed

+84
-20
lines changed

src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,22 @@ class ResizeFormListener implements EventSubscriberInterface
3030
protected $allowDelete;
3131

3232
private $deleteEmpty;
33+
private $keepAsList;
3334

3435
/**
3536
* @param bool $allowAdd Whether children could be added to the group
3637
* @param bool $allowDelete Whether children could be removed from the group
3738
* @param bool|callable $deleteEmpty
39+
* @param bool $keepAsList Whether children should be renamed with sequential keys after submit
3840
*/
39-
public function __construct(string $type, array $options = [], bool $allowAdd = false, bool $allowDelete = false, $deleteEmpty = false)
41+
public function __construct(string $type, array $options = [], bool $allowAdd = false, bool $allowDelete = false, $deleteEmpty = false, $keepAsList = false)
4042
{
4143
$this->type = $type;
4244
$this->allowAdd = $allowAdd;
4345
$this->allowDelete = $allowDelete;
4446
$this->options = $options;
4547
$this->deleteEmpty = $deleteEmpty;
48+
$this->keepAsList = $keepAsList;
4649
}
4750

4851
public static function getSubscribedEvents()
@@ -164,6 +167,20 @@ public function onSubmit(FormEvent $event)
164167
}
165168
}
166169

170+
if ($this->keepAsList) {
171+
$formReindex = [];
172+
foreach ($form as $name => $child) {
173+
$formReindex[] = $child;
174+
$form->remove($name);
175+
}
176+
foreach ($formReindex as $index => $child) {
177+
$form->add($index, $this->type, array_replace([
178+
'property_path' => '['.$index.']',
179+
], $this->options));
180+
}
181+
$data = array_values($data);
182+
}
183+
167184
$event->setData($data);
168185
}
169186
}

src/Symfony/Component/Form/Extension/Core/Type/CollectionType.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ public function buildForm(FormBuilderInterface $builder, array $options)
4545
$options['entry_options'],
4646
$options['allow_add'],
4747
$options['allow_delete'],
48-
$options['delete_empty']
48+
$options['delete_empty'],
49+
$options['keep_as_list']
4950
);
5051

5152
$builder->addEventSubscriber($resizeListener);
@@ -126,10 +127,12 @@ public function configureOptions(OptionsResolver $resolver)
126127
? $previousValue
127128
: 'The collection is invalid.';
128129
},
130+
'keep_as_list' => false,
129131
]);
130132

131133
$resolver->setNormalizer('entry_options', $entryOptionsNormalizer);
132134
$resolver->setAllowedTypes('delete_empty', ['bool', 'callable']);
135+
$resolver->setAllowedTypes('keep_as_list', ['bool']);
133136
}
134137

135138
/**

src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -192,21 +192,7 @@ public function testErrorPathOnCollections()
192192
->setMetadataFactory($metadataFactory)
193193
->getValidator();
194194

195-
$form = Forms::createFormFactoryBuilder()
196-
->addExtension(new ValidatorExtension($validator))
197-
->getFormFactory()
198-
->create(FormTypeTest::TESTED_TYPE, new Organization([]), [
199-
'data_class' => Organization::class,
200-
'by_reference' => false,
201-
])
202-
->add('authors', CollectionTypeTest::TESTED_TYPE, [
203-
'entry_type' => AuthorType::class,
204-
'allow_add' => true,
205-
'allow_delete' => true,
206-
])
207-
;
208-
209-
$form->submit([
195+
$submitData = [
210196
'authors' => [
211197
0 => [
212198
'firstName' => '', // Fires a Not Blank Error
@@ -222,7 +208,23 @@ public function testErrorPathOnCollections()
222208
'lastName' => 'lastName3',
223209
],
224210
],
225-
]);
211+
];
212+
213+
$form = Forms::createFormFactoryBuilder()
214+
->addExtension(new ValidatorExtension($validator))
215+
->getFormFactory()
216+
->create(FormTypeTest::TESTED_TYPE, new Organization([]), [
217+
'data_class' => Organization::class,
218+
'by_reference' => false,
219+
])
220+
->add('authors', CollectionTypeTest::TESTED_TYPE, [
221+
'entry_type' => AuthorType::class,
222+
'allow_add' => true,
223+
'allow_delete' => true,
224+
])
225+
;
226+
227+
$form->submit($submitData);
226228

227229
//Form behaves right (...?). It has index 0, 2 and 3 (1 has been removed)
228230
$this->assertTrue($form->get('authors')->has('0'));
@@ -242,11 +244,53 @@ public function testErrorPathOnCollections()
242244
];
243245

244246
$this->assertContains('data.authors[0].firstName', $errorPaths);
245-
$this->assertNotContains('data.authors[1].firstName', $errorPaths);
247+
$this->assertContains('data.authors[1].firstName', $errorPaths);
246248
$this->assertContains('data.authors[2].firstName', $errorPaths);
247-
$this->assertContains('data.authors[3].firstName', $errorPaths);
249+
$this->assertNotContains('data.authors[3].firstName', $errorPaths);
248250

249251
//In fact, root form should NOT contain errors but it does
252+
$this->assertCount(1, $form->getErrors(false));
253+
254+
//Let's do this again, but with "keep_as_list" option set to true
255+
$form = Forms::createFormFactoryBuilder()
256+
->addExtension(new ValidatorExtension($validator))
257+
->getFormFactory()
258+
->create(FormTypeTest::TESTED_TYPE, new Organization([]), [
259+
'data_class' => Organization::class,
260+
'by_reference' => false,
261+
])
262+
->add('authors', CollectionTypeTest::TESTED_TYPE, [
263+
'entry_type' => AuthorType::class,
264+
'allow_add' => true,
265+
'allow_delete' => true,
266+
'keep_as_list' => true,
267+
])
268+
;
269+
270+
$form->submit($submitData);
271+
272+
//Errors paths are not messing up now
273+
$this->assertTrue($form->get('authors')->has('0'));
274+
$this->assertTrue($form->get('authors')->has('1'));
275+
$this->assertTrue($form->get('authors')->has('2'));
276+
$this->assertNotTrue($form->get('authors')->has('3'));
277+
278+
//Form does have 3 not blank errors
279+
$errors = $form->getErrors(true);
280+
$this->assertCount(3, $errors);
281+
282+
$errorPaths = [
283+
$errors[0]->getCause()->getPropertyPath(),
284+
$errors[1]->getCause()->getPropertyPath(),
285+
$errors[2]->getCause()->getPropertyPath(),
286+
];
287+
288+
$this->assertContains('data.authors[0].firstName', $errorPaths);
289+
$this->assertContains('data.authors[1].firstName', $errorPaths);
290+
$this->assertContains('data.authors[2].firstName', $errorPaths);
291+
$this->assertNotContains('data.authors[3].firstName', $errorPaths);
292+
293+
//Root form does NOT contain errors
250294
$this->assertCount(0, $form->getErrors(false));
251295
}
252296
}

0 commit comments

Comments
 (0)