ux icon indicating copy to clipboard operation
ux copied to clipboard

[LiveComponent] Validation doesn't seem to work

Open javiereguiluz opened this issue 5 months ago • 4 comments

Hi team!

I'm trying to validate a property of some LiveComponent that doesn't use a Symfony Form. I'm following this: https://symfony.com/bundles/ux-live-component/current/index.html#validation-without-a-form

My code is like this:

#[AsLiveComponent]
class MyComponent
{
    use DefaultActionTrait;
    use ValidatableComponentTrait;

    #[LiveProp(writable: true)]
    #[Assert\Choice(choices: ['foo', 'bar'])]
    public string $type;

    // ...
}

If I put this in my template, I expect to see an error, but I don't see anything. The LiveComponent renders normally, without validating the value of the $type property:

<twig:MyComponent type="aaaaa"/>

Also, on the Symfony Docs, I don't understand the followin:

Be sure to add the IsValid attribute/annotation to any property
where you want the object on that property to also be validated.

The docs doesn't show any example using that IsValid attribute and I'm not sure where to find it. Thanks!

javiereguiluz avatar Aug 05 '25 07:08 javiereguiluz

I think that sentence is a mistake in the documentation.

Be sure to add the IsValid attribute/annotation to any property where you want the object on that property to also be validated.

I think it's a typo and should be Valid instead of Isvalid. You can see the example with #[Assert\Valid] added to the $user property. We add the Valid constraint when we want to check validation constraints of the related object (the User object in the example). But the Valid constraint is only used to validate objects, so it's probably not related to your issue.

Seb33300 avatar Aug 06 '25 08:08 Seb33300

Hi, yes there is a typo on IsValid attribute, it should be Valid insteadd but it will only works for object.

About your validation error, the method $this->validate() is responsible for validating your props. It is automatically called in validateAfterHydration during PostHydrate hook, but that only works when the component state has been is loaded from the client (i.e.: after triggering a LiveAction).

To validate your component props at initial render, you must call $this->validate(throw: false) by yourself, during a PostMount hook, example:

<?php

namespace App\Twig\Components;

use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\DefaultActionTrait;
use Symfony\UX\LiveComponent\ValidatableComponentTrait;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\UX\TwigComponent\Attribute\PostMount;

#[AsLiveComponent]
final class ComponentWithValidation
{
    use DefaultActionTrait;
    use ValidatableComponentTrait;

    #[LiveProp(writable: true)]
    #[Assert\Choice(choices: ['foo', 'bar'])]
    public string $type;

    #[PostMount]
    public function initialValidation(): void
    {
        $this->validate(false);
    }
}

With this modification on your component, I'm able to see the validation errors at initial rendering

Image

The documentation could be fixed, improved, and tests aswell

Kocal avatar Aug 07 '25 07:08 Kocal

Thanks for the detailed answer. I'm going to play with this a bit and I'll propose some doc tweaks after that.

The only thing I don't like much is this: $this->validate(false); It totally looks like "DON'T validate this" but it's the opposite.

javiereguiluz avatar Aug 07 '25 07:08 javiereguiluz

Yeah, that's like Response::getHeaders() from HttpClient, but using named arguments helps a lot :)

Kocal avatar Aug 07 '25 07:08 Kocal