Installation:
composer require alxishin/ordered-form-bundle
Ensure your config/bundles.php includes:
return [
// ...
Ivory\OrderedFormBundle\IvoryOrderedFormBundle::class => ['all' => true],
];
First Use Case: Define a form with ordered fields in your form builder:
use Ivory\OrderedFormBundle\Form\Type\OrderedFormType;
$builder->add('field1', TextType::class);
$builder->add('field2', TextType::class, [
'position' => ['before' => 'field1'] // Places field2 before field1
]);
Key Files:
Resources/doc/usage.md: Core usage patterns.Form/Type/OrderedFormType.php: Base class for ordered forms.Dynamic Ordering:
Use position options in add() to define relationships:
$builder->add('title', TextType::class, ['position' => 'first']);
$builder->add('content', TextareaType::class, ['position' => 'last']);
Conditional Ordering: Dynamically adjust ordering in form events:
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
if ($event->getData()->isPremium()) {
$form->get('payment')->setPosition(['after' => 'shipping']);
}
});
Nested Forms: Apply ordering to nested collections:
$builder->add('steps', CollectionType::class, [
'entry_type' => StepType::class,
'allow_add' => true,
'position' => ['after' => 'intro']
]);
Reordering via JavaScript:
Use Symfony UX Live Component or custom JS to update data-position attributes and submit via AJAX.
FormBuilder.form_row() with form_widget() for manual rendering if needed.Circular Dependencies:
Avoid before/after loops (e.g., A before B and B before A). The bundle throws a LogicException.
Dynamic Forms: If adding/removing fields dynamically (e.g., via AJAX), ensure positions are recalculated:
$form->get('dynamic_field')->setPosition(['after' => 'static_field']);
Legacy Forms: The bundle assumes Symfony 2.7+ forms. For older versions, check compatibility or fork.
Position Conflicts:
Enable debug mode to see rendered HTML with data-position attributes. Conflicts appear as overlapping or missing fields.
Event Order:
Use FormEvents::PRE_SUBMIT for position changes that must persist across validation.
Custom Position Logic:
Extend Ivory\OrderedFormBundle\Position\PositionResolver to add custom rules (e.g., "group by section").
Template Overrides:
Override IvoryOrderedFormBundle:Form:fields.html.twig to customize rendering logic.
Position Storage: For complex apps, store positions in the database and hydrate forms dynamically:
$form->add('field', TextType::class, [
'position' => $this->getFieldPositionFromDb($fieldName)
]);
position: 'first' or position: 'last' for simple cases to avoid complex arrays.assertContains() on rendered HTML or assertSame() on form->all().How can I help you explore Laravel packages today?