Symfony 8.2 New Published on

One field for a date range, with BoundsType

Two dates and the rule that orders them fit in a single field: no more POST_SUBMIT listener comparing the bounds by hand.

Topics covered: Forms

New in Symfony 8.2 (in development). A range (two dates, two prices, two sizes) used to be declared as two fields, and the rule that ties them together had nowhere to live: it ended up in a POST_SUBMIT listener copied from one form to the next. BoundsType renders both bounds with the same type and takes care of the comparison.

Before

$builder
    ->add('from', DateType::class, ['widget' => 'single_text', 'label' => 'From'])
    ->add('to', DateType::class, ['widget' => 'single_text', 'label' => 'To'])
    ->addEventListener(FormEvents::POST_SUBMIT, static function (FormEvent $event): void {
        // compare the two dates, put the error on the right one…
    });

Since Symfony 8.2

$builder->add('period', BoundsType::class, [
    'type' => DateType::class,
    'options' => ['widget' => 'single_text'],
    'from_options' => ['label' => 'From'],
    'to_options' => ['label' => 'To'],
    'compare' => true,
    'compare_message' => 'The start date must come before the end date.',
]);

The field has two children, from and to, rendered by the type passed in type. options applies to both; from_options and to_options are merged on top for what sets them apart. Like any compound field, it has its own label, guessed from its name: label: false removes it. compare: true checks the order of the bounds and reports the error on the lower bound, the one that must move; dates, scalars and enums are ordered on their own, any other kind of bound needs a callable.

An empty bound is still allowed: compare only deals with closed ranges, and the field returns null (not ['from' => null, 'to' => null]) when both bounds are empty.

Your task

In RechercheType, replace the two date fields with a single period field, and let BoundsType compare the bounds: the listener no longer has a reason to exist. Update EmpruntsController, which now reads both bounds from the field's data. The /loans page must behave as before, labels and error message included.

Where the feature comes from: the original pull request.