[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` * Added a `choice_translation_parameters` option to `ChoiceType`
* Add `UuidType` and `UlidType` * Add `UuidType` and `UlidType`
* Dependency on `symfony/intl` was removed. Install `symfony/intl` if you are using `LocaleType`, `CountryType`, `CurrencyType`, `LanguageType` or `TimezoneType`. * 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 5.2.0
----- -----

View File

@ -107,6 +107,7 @@ abstract class BaseType extends AbstractType
'translation_domain' => $translationDomain, 'translation_domain' => $translationDomain,
'label_translation_parameters' => $labelTranslationParameters, 'label_translation_parameters' => $labelTranslationParameters,
'attr_translation_parameters' => $attrTranslationParameters, 'attr_translation_parameters' => $attrTranslationParameters,
'priority' => $options['priority'],
// Using the block name here speeds up performance in collection // Using the block name here speeds up performance in collection
// forms, where each entry has the same full block name. // forms, where each entry has the same full block name.
// Including the type is important too, because if rows of a // Including the type is important too, because if rows of a
@ -135,11 +136,15 @@ abstract class BaseType extends AbstractType
'attr' => [], 'attr' => [],
'translation_domain' => null, 'translation_domain' => null,
'auto_initialize' => true, 'auto_initialize' => true,
'priority' => 0,
]); ]);
$resolver->setAllowedTypes('block_prefix', ['null', 'string']); $resolver->setAllowedTypes('block_prefix', ['null', 'string']);
$resolver->setAllowedTypes('attr', 'array'); $resolver->setAllowedTypes('attr', 'array');
$resolver->setAllowedTypes('row_attr', 'array'); $resolver->setAllowedTypes('row_attr', 'array');
$resolver->setAllowedTypes('label_html', 'bool'); $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); $view->children[$name] = $child->createView($view);
} }
$this->sort($view->children);
$type->finishView($view, $this, $options); $type->finishView($view, $this, $options);
return $view; 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. * 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['child1']->vars['attr']['form']);
$this->assertSame($view->vars['id'], $view['child2']->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 class Money

View File

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

View File

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

View File

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

View File

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