[Form] Add support for sorting fields

This commit is contained in:
Yonel Ceruto 2021-04-02 09:52:16 -04:00 committed by Nyholm
parent bb1e1e58ae
commit 62650bbdc7
No known key found for this signature in database
GPG Key ID: D6332DE2B6F8FA38
8 changed files with 60 additions and 0 deletions

View File

@ -15,6 +15,7 @@ CHANGELOG
* Added a `choice_translation_parameters` option to `ChoiceType`
* Add `UuidType` and `UlidType`
* Dependency on `symfony/intl` was removed. Install `symfony/intl` if you are using `LocaleType`, `CountryType`, `CurrencyType`, `LanguageType` or `TimezoneType`.
* Add `priority` option to `BaseType` and sorting view fields
5.2.0
-----

View File

@ -107,6 +107,7 @@ abstract class BaseType extends AbstractType
'translation_domain' => $translationDomain,
'label_translation_parameters' => $labelTranslationParameters,
'attr_translation_parameters' => $attrTranslationParameters,
'priority' => $options['priority'],
// Using the block name here speeds up performance in collection
// forms, where each entry has the same full block name.
// Including the type is important too, because if rows of a
@ -135,11 +136,15 @@ abstract class BaseType extends AbstractType
'attr' => [],
'translation_domain' => null,
'auto_initialize' => true,
'priority' => 0,
]);
$resolver->setAllowedTypes('block_prefix', ['null', 'string']);
$resolver->setAllowedTypes('attr', 'array');
$resolver->setAllowedTypes('row_attr', 'array');
$resolver->setAllowedTypes('label_html', 'bool');
$resolver->setAllowedTypes('priority', 'int');
$resolver->setInfo('priority', 'The form rendering priority (higher priorities will be rendered first)');
}
}

View File

@ -1044,11 +1044,38 @@ class Form implements \IteratorAggregate, FormInterface, ClearableErrorsInterfac
$view->children[$name] = $child->createView($view);
}
$this->sort($view->children);
$type->finishView($view, $this, $options);
return $view;
}
/**
* Sorts view fields based on their priority value.
*/
private function sort(array &$children): void
{
$c = [];
$i = 0;
$needsSorting = false;
foreach ($children as $name => $child) {
$c[$name] = ['p' => $child->vars['priority'] ?? 0, 'i' => $i++];
if (0 !== $c[$name]['p']) {
$needsSorting = true;
}
}
if (!$needsSorting) {
return;
}
uksort($children, static function ($a, $b) use ($c): int {
return [$c[$b]['p'], $c[$a]['i']] <=> [$c[$a]['p'], $c[$b]['i']];
});
}
/**
* Normalizes the underlying data if a model transformer is set.
*

View File

@ -836,6 +836,29 @@ class FormTypeTest extends BaseTypeTest
$this->assertSame($view->vars['id'], $view['child1']->vars['attr']['form']);
$this->assertSame($view->vars['id'], $view['child2']->vars['attr']['form']);
}
public function testSortingViewChildrenBasedOnPriorityOption()
{
$view = $this->factory->createNamedBuilder('parent', self::TESTED_TYPE)
->add('child1', null, ['priority' => -1])
->add('child2')
->add('child3', null, ['priority' => -1])
->add('child4')
->add('child5', null, ['priority' => 1])
->add('child6')
->getForm()
->createView();
$expected = [
'child5',
'child2',
'child4',
'child6',
'child1',
'child3',
];
$this->assertSame($expected, array_keys($view->children));
}
}
class Money

View File

@ -57,6 +57,7 @@
"mapped",
"method",
"post_max_size_message",
"priority",
"property_path",
"required",
"row_attr",

View File

@ -34,6 +34,7 @@ Symfony\Component\Form\Extension\Core\Type\ChoiceType (Block prefix: "choice")
mapped
method
post_max_size_message
priority
property_path
required
row_attr

View File

@ -35,6 +35,7 @@
"mapped",
"method",
"post_max_size_message",
"priority",
"property_path",
"required",
"row_attr",

View File

@ -37,6 +37,7 @@ Symfony\Component\Form\Extension\Core\Type\FormType (Block prefix: "form")
mapped
method
post_max_size_message
priority
property_path
required
row_attr