symfonysymfony6symfonyux

Symfony UX - LiveComponent problem with html5 date


I implemented LiveComponent on my form containing a date and other fields.

I use a DateType field compatible with html5. When I use my form and type a date that starts with 0 (eg: 05/10/2024), I have the following error: "Expected argument of type "DateTimeImmutable", "null" given at property path "operationDate".

When the date is greater than the 9th of the month (eg: 15/10/2024), I have no problem.

The entity

Here my form

<?php

namespace App\Form\Transaction;

use App\Entity\Transaction\BalanceTransaction;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class BalanceTransactionType extends AbstractType
{
    #[\Override]
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('operationDate', DateType::class, [
                'widget' => 'single_text',
                'label' => 'Operation date',
                'html5' => true,
                'input' => 'datetime_immutable',
                'required' => true,
            ])
            ->add('label', TextType::class, [
                'label' => 'Label',
                'required' => false,
            ])
        ;
    }

    #[\Override]
    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => BalanceTransaction::class,
        ]);
    }
}

Here my component

<?php

namespace App\Twig\Components\Transaction;

use App\Entity\Transaction\BalanceTransaction;
use App\Form\Transaction\BalanceTransactionType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\ComponentWithFormTrait;
use Symfony\UX\LiveComponent\DefaultActionTrait;
use Symfony\UX\LiveComponent\LiveCollectionTrait;

#[AsLiveComponent()]
class BalanceTransactionForm extends AbstractController
{
    use DefaultActionTrait;
    use LiveCollectionTrait;

    #[LiveProp(fieldName: 'formData')]
    public ?BalanceTransaction $transaction = null;

    #[LiveProp(fieldName: 'bankAccountId')]
    public string $bankAccountId;

    protected function instantiateForm(): FormInterface
    {
        return $this->createForm(
            BalanceTransactionType::class,
            $this->transaction
        );
    }
}

In my example the entity with the value operationDate filled in. When I start changing the first two digits (the first of which starts with 0) (dd/mm/yyyyy format) and the cursor moves to the month, a request (ajax via symfony ux) is triggered and causes the error.

Here is the data that was posted

{"props":{"formData":[],"bankAccountId":"019238f6-fcb2-7c6d-be74-6d001c779421","formName":"balance_transaction","balance_transaction":{"operationDate":"2024-10-10","label":"","_token":"3ad.wmTGi7VbU2Uh3D8--6ezcR1XbpIJ-yYn8zTLxPPb6-g.lAvw54ZqKwxS7H1JmuiDFGpuBso_gRJspH6v9L6Snt-aVvXbgTUUAmWIBw"},"isValidated":false,"validatedFields":[],"@attributes":{"id":"live-3733654337-0"},"@checksum":"XLsH+D2OqDJQKXr/ZLKyZmJvtHtlR6xVfgoy9GGp8gg="},"updated":{"balance_transaction.operationDate":"","validatedFields":["balance_transaction.operationDate"]}}

the new date is send empty

I'm trying to apply a debouncing on this field, but I can't do it. I break the automatic update of LiveComponent for this field.

data-model="debounce(100)|operationDate"

Solution

  • Ok, I found a solution with the "debounce", but I had applied it wrongly because directly on an entity object.

    In the twig

    {{ form_row(form.operationDate, {'attr': { 'data-model': 'debounce(200)|account_transaction.operationDate' }} ) }}
    

    My mistake was the wrong naming of the data-model. It should point to the object first and then the attribute (and not directly to the attribute).

    Also, the value of debounce must be large enough to wait until the input is complete, but also too large for the event to be passed on anyway. In my case, I chose a value of 200 ms, after a few tries.