symfony / ux

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

[Live Component] Are file uploads supported? #486

Open benr77 opened 1 year ago

benr77 commented 1 year ago

Hello again. I'm trying to do a file upload in a Live Component. I've tried with both DropzoneType and the regular FileType but running into the same problem I think.

I have been reading related issues #354, #289, #299 etc but I'm unsure of the current state of play. I believe these discussions are only related to using a UX component such as Dropzone inside the Live Component.

Even with a standard FileType field in the form, as soon as I add a file to be uploaded to the form field, the component reloads and I think the file to be uploaded is lost, so when I then submit the form it sends empty data for the file field.

I can live without Dropzone support in the Live Component for the moment, but of course that would be great to have - but should the standard FileType field work?

How can I stop the Live Component re-rendering and losing the selected file as soon as I add the file to the field?

Thank you.

talanon commented 1 year ago

Hey, I tried many things to send file with Live Components. The only way I found is to force norender on my form and to send manually my file with stimulusJS.

{{ form_start(form, { attr: { 'data-action': 'live#action', 'data-action-name': 'prevent|save', 'data-model': 'norender|*' } }) }}

I personnaly wait DropzoneType or FileType to be supported before reuse Live Component

kbond commented 1 year ago

Hey @benr77,

Not officially supported yet. We want to support this in a way that allows using a filesystem abstractions (Flysystem). I've been hacking on a sort of symfony-flysystem bridge to help with this.

Long story, short, it's definitely on our radar!

benr77 commented 1 year ago

OK, great thanks for the update. I'll just implement my file upload outside of a Live Component for the time being.

This will be a great feature - I'm finding Live Components are so powerful for decoupling my front end I'm trying to use them at every opportunity.

Skarlax commented 1 year ago

Hey, I am experiencing the same issue. Any news on this topic ?

Skarlax commented 1 year ago

Hey @kbond

Do you know when will this feature be supported ?

kbond commented 1 year ago

Hey! This is still on my radar but I've been busy with other things lately. Rest assured it hasn't been forgotten but I don't have an ETA at this time.

Skarlax commented 1 year ago

Thanks for your reply and good luck for this feature !

talanon commented 1 year ago

Hi!

Any news about this issue ?

kbond commented 1 year ago

https://github.com/symfony/ux/pull/834 is the latest iteration I think we'll be going with.

lukepass commented 10 months ago

Hello, I commented in #834 but it's a pull requst and not an issue. I tried to upload a file with version 2.9.1 (it should support files as in documentation) but an error appears in the console saying Unknown modifier files in action "files|prevent|save". Available modifiers are: prevent, stop, self, debounce.. Thanks.

norkunas commented 10 months ago

Hello, I commented in #834 but it's a pull requst and not an issue. I tried to upload a file with version 2.9.1 (it should support files as in documentation) but an error appears in the console saying Unknown modifier files in action "files|prevent|save". Available modifiers are: prevent, stop, self, debounce.. Thanks.

I think that's a wrong assumption in docs, because only v2.11 released file upload

benr77 commented 5 months ago

Thanks for all the hard work getting this feature up and running!

I see there is an example on the UX site showing how to do file uploads inside Live Components, but it does not use Symfony Forms.

I have almost got it working using the Form component, but the file field in the form data class is always null. I have a hack to add it from the Request object directly:

$this->submitForm();

/** @var MyFormData $formData */
$formData = $this->getForm()->getData();

// Hack to put the actual UploadedFile object on to the form data class
$formData->mapFile = $request->files->all('form_name')['pdfFile'];

This seems to work OK, but I think it means that any validation constraints on the UploadedFile in the form data class are ignored.

Does all this sound about right based on the current state of support for file uploads inside Live Components?

Thanks!

bastien70 commented 5 months ago

I agree, something is missing to properly manage uploads using the Symfony form.

In my case, I use VichUploader on a Media entity to store all my files. I have an entity that has a Media collection, and I use LiveCollectionType to render this media collection. I submit the form via the component

{{ form_start(form, {attr: {
        'data-action': 'live#action',
        'data-action-name': 'prevent|files|save',
    }}) }}

In the component, I'm doing something like this to handle files and place them in correct collection position :

    #[LiveAction]
    public function save(EntityManagerInterface $entityManager, Request $request): void
    {
        $files = $request->files->all();

        if (\array_key_exists('meeting_point', $files)) {
            foreach ($files['meeting_point']['medias'] as $key => $file) {
                $uploadedFile = $file['file']['file'];
                $this->formValues['medias'][$key]['file']['file'] = $uploadedFile;
            }
        }

        $this->submitForm();

        /** @var MeetingPoint $meetingPoint */
        $meetingPoint = $this->getForm()->getData();

        $entityManager->persist($meetingPoint);
        $entityManager->flush();
    }

It seems to work.

I wonder if we could set up something generic to automatically correctly map the submitted files with the entities to which they should belong, and therefore obtain the same operation as for a symfony form submitted and managed from the controller

kbond commented 1 month ago

Hello, I want to provide a bit of an update on this issue/feature - it is still very much on my radar.

What we need are some pieces in place before we can add this feature in a robust way. Let me explain: