symfony / ux

Symfony UX initiative: a JavaScript ecosystem for Symfony
https://ux.symfony.com/
MIT License
818 stars 298 forks source link

[LiveComponent] Form submission logic and validation #1457

Open gremo opened 7 months ago

gremo commented 7 months ago

I'm digging into live components last two weeks. I don't know if it's just me but the documentation doesn't clarify some aspects when using live components with forms (entire forms).


Validation & submitting: if I type in my <input> and then focus out, the field is validated but not submitted, the save() action of my AttendanceForm component isn't invoked at all. Is there a way to enable validation ONLY if form is actually submitted, and not on the field change?

It seems that data-model="on(change)|identifier" does exactly this, but according to the documentation this applies when using validation without forms.


Missing from documentation: submit the form if typing in the <input> field, after a short delay. How do I add autosubmit after user type on a field, with a delay of 500ms?

This is not working: data-model="on(input)" just only validating the form as I type (not submitting).

namespace App\Twig\Components;

use App\Core\Model\AttendanceDto;
use App\Form\Type\AttendanceType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveAction;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\ComponentWithFormTrait;
use Symfony\UX\LiveComponent\DefaultActionTrait;

#[AsLiveComponent]
class AttendanceForm extends AbstractController
{
    use DefaultActionTrait;
    use ComponentWithFormTrait;

    #[LiveProp]
    public ?AttendanceDto $initialFormData = null;

    #[LiveProp]
    public bool $success = false;

    #[LiveAction]
    public function save()
    {
        $this->submitForm();
        $this->success = true;
    }

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

And the model:

namespace App\Core\Model;

use Symfony\Component\Validator\Constraints as Assert;

class AttendanceDto
{
    #[Assert\NotBlank]
    public ?string $identifier;
}

... and the rendering:

<div {{ attributes }}>
    {{ form_start(form, {
        attr: {
            'data-action': 'live#action',
            'data-action-name': 'prevent|save',
        }
    }) }}
    {{ form_end(form) }}
</div>
carsonbot commented 1 month ago

Thank you for this issue. There has not been a lot of activity here for a while. Has this been resolved?

carsonbot commented 4 weeks ago

Friendly ping? Should this still be open? I will close if I don't hear anything.

carsonbot commented 2 weeks ago

Hey,

I didn't hear anything so I'm going to close it. Feel free to comment if this is still relevant, I can always reopen!

PaulRequillartDole commented 1 week ago

Still relevant !