Skip to content

[LiveComponent][Docs] File upload & validation #3737

Description

@DavidPetrasek

The current documentation for Uploading files focuses primarily on handling files via dedicated/separate live actions.

However, it does not cover the common scenario where a file must be validated and uploaded atomically in a single submit action along with the rest of the form.

Related:
https://www.reddit.com/r/symfony/comments/1u8802a/comment/os86cu9/
https://stackoverflow.com/questions/79943827/symfony-ux-live-components-file-validation-only-triggers-after-other-fields-pas

The Solution

In order to validate the file along with the rest of the form using only a single action, the file from $request->files needs to be explicitly assigned to $this->formValues prior to calling the $this->submitForm()

Example Implementation

1. Component Class (RegistrationForm.php):

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

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

    #[LiveAction]
    public function save(Request $request)
    {
        // File needs to be added explicitly before submission and validation
        $files = $request->files->get('registration');
        $this->formValues['profile_picture'] = $files['profile_picture'];

        $this->submitForm();

        // Save data along with the file/files ...

        $this->addFlash('success', 'Saved!');
        return $this->redirectToRoute('foo');
    }
}

2. Form Type (RegistrationType.php):

->add('profile_picture', FileType::class,
        [
            'mapped' => false,
            'required' => false,
            'multiple' => false,
            'constraints' =>
            [
                new File
                (
                    extensions:
                    [
                        'jpg' =>'image/jpeg',
                        'jpeg' =>'image/jpeg',
                        'png' => 'image/png',
                    ],
                    extensionsMessage: 'File with extension {{ extension }} is not allowed. Allowed extension: {{ extensions }}.',
                    maxSize: '2M',
                )
            ],
        ])

3. Twig Component (registration_form.html.twig):

<div {{ attributes }} >
    
    {{ form_start(form, {attr:
        {
            'data-action': 'live#action:prevent',
            'data-live-action-param': 'files|save'
        }})
    }}

    {{ form_errors(form) }}

    {{ form_widget(form.profile_picture) }}                 
    {{ form_errors(form.profile_picture) }}

    {# Other fields ... #}

    {{ form_end(form) }}

</div>

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions