filament icon indicating copy to clipboard operation
filament copied to clipboard

FileUpload doesn't work as intended in Repeater of Relation Manager

Open faizanakbar10 opened this issue 7 months ago • 9 comments

Package

filament/filament

Package Version

v3.3.14

Laravel Version

v12.13.0

Livewire Version

No response

PHP Version

8.2

Problem description

I have Brand Resource with Categories Relation Manager.

In Categories Relation Manager, I have repeater for Menu Items that has File Upload for image.

After submitting the form: It doesn't let me click on the 'x' button to remove the image. Also when changing the image, it doesn't work. Need to upload the image twice.

Expected behavior

On clicking 'x' it should remove the image as it does normally. Uploading image on edit should work as intended.

Steps to reproduce

Use the repo I created. In that first create a brand, then create category with menu items. Now upload image for 1 menu item and save. Now open the same category with menu item and try removing the image. Doesn't work. Now try to change the image of that menu item, there will be an issue. Need to upload the same image twice.

Reproduction repository (issue will be closed if this is not valid)

https://github.com/faizanakbar10/filament-fileupload-repeater-issue

Relevant log output


faizanakbar10 avatar May 12 '25 12:05 faizanakbar10

Hey @faizanakbar10! We're sorry to hear that you've hit this issue. 💛

However, it looks like you forgot to fill in the reproduction repository URL. Can you edit your original post and then we'll look at your issue?

We need a public GitHub repository which contains a Laravel app with the minimal amount of Filament code to reproduce the problem. Please do not link to your actual project, what we need instead is a minimal reproduction in a fresh project without any unnecessary code. This means it doesn't matter if your real project is private / confidential, since we want a link to a separate, isolated reproduction. That would allow us to download it and review your bug much easier, so it can be fixed quicker. Please make sure to include a database seeder with everything we need to set the app up quickly.

github-actions[bot] avatar May 12 '25 12:05 github-actions[bot]

Thank you for providing reproduction steps! Reopening the issue now.

github-actions[bot] avatar May 12 '25 12:05 github-actions[bot]

We're having the same issue with a Repeater that contains a FileUpload field, ever since Filament 3.3.17 and still with the latest 3.3.29:

FileUpload::make('template')
    ->label(fn() => static::translate('form.document_templates.form.template'))
    ->disk('bucket1')
    ->directory('templates')
    ->visibility('private')
    ->preserveFilenames()
    ->downloadable()
    ->hint('Word (.docx)')
    ->acceptedFileTypes([
        MimeTypeEnum::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlDocument->value,
    ]),

.filepond--drop-label and .filepond--list-scroller are on top of each other, and changing their z-index makes either one usable at a time.

Image

I'm not a frontend developer, and I was unfortunately unable to fix this by overriding some CSS through a theme.

Also, none of these fileupload field style configurations fix the issue:

->loadingIndicatorPosition('left')
->panelAspectRatio('2:1')
->panelLayout('integrated')
->removeUploadedFileButtonPosition('right')
->uploadButtonPosition('left')
->uploadProgressIndicatorPosition('left')
->panelLayout('grid')
 ->pasteable(false)

k3rielit avatar Jun 30 '25 13:06 k3rielit

@k3rielit your issue is unrelated and should be fixed by #16900 (you can backport it to v3 via a PR once it is merged into v4)

danharrin avatar Jul 11 '25 10:07 danharrin

Seems like a FilePond bug, and only when the repeater is set to collapsed(). If the repeater is collapsible() but not collapsed by default, it also works fine.

danharrin avatar Jul 11 '25 11:07 danharrin

I have the same problem on v3.3.17 and new information on it.

This problem really only appears when the repeater is set to collapsed(). But you can also catch this bug in superposition. Case: we have a page with a repeater with collapsed(), which has many blocks, some of them have a FileUpload component. So:

  1. go to the page
  2. wait for the page to load
  3. uncollapse one of the blocks that has FileUpload to make visible it content
  4. but also leave at least one block with FileUpload in the collapsed state
  5. as a result, if you have right time, you will get this state for the block from point (3)
Image Image and such a state for the block from point (4) Image Image

Block (3) appears to be fully functional: the cross button to delete a file works, and the filepond--drop-label with text is not displayed over the file. And block (4) looks broken: you can't click the cross button to delete a file (clicking on it or around it calls the file adding functionality), a filepond--drop-label is displayed over the image, which looks foreign, and apparently it is clicking on it that triggers the adding functionality. This superposition state is not corrected by collapsing and uncollapsing blocks. These inline styles are apparently set using filament js, and that's why you can catch such a superposition. That's why I think it won't be possible to fix this using custom css (I tried unsuccessfully to use overflow-hidden from your commit a6e7650 for filament v4). And writing custom js to overwrite this problem seems like an incorrect solution. Apparently, inline styles for collapsed blocks should always be the same as for expanded ones.

I hope this information will help correct the behavior.

TantonFirst avatar Sep 02 '25 13:09 TantonFirst

@TantonFirst Thanks for the example, I have this exact problem in a collapsed repeater that can't really be uncollapsed because the form is huge.

I don't think it's JS, it must be a style, because the DOM/HTML is the same for both a regular fileupload compoment and a broken one, and uncollapsing everything won't fix it.

I tried writing a userscript that tries to fix this but I've been unsuccessful so far.

Broken fileupload example:

<div class="filepond--root filepond--hopper" data-style-panel-layout="compact"
    data-style-button-remove-item-position="left" data-style-button-process-item-position="right"
    data-style-load-indicator-position="right" data-style-progress-indicator-position="right"
    data-style-button-remove-item-align="false" data-style-image-edit-button-edit-item-position="bottom center"
    style="height: 76px;"><input class="filepond--browser" type="file" id="filepond--browser-avj6z91jj" aria-controls="filepond--assistant-avj6z91jj" aria-labelledby="filepond--drop-label-avj6z91jj" accept="application/vnd.openxmlformats-officedocument.wordprocessingml.document">
    <div class="filepond--drop-label" style="transform: translate3d(0px, 0px, 0px); opacity: 1;">
        <label for="filepond--browser-avj6z91jj" id="filepond--drop-label-avj6z91jj">Mozgasd ide a fájlt a feltöltéshez, vagy <span class="filepond--label-action" tabindex="0"> tallózás </span></label>
    </div>
    <div class="filepond--list-scroller" style="transform: translate3d(0px, 0px, 0px);">
        <ul class="filepond--list" role="list">
            <li class="filepond--item" id="filepond--item-7nnnybr2g" data-filepond-item-state="idle"
                style="transform: translate3d(0px, 0px, 0px) scale3d(1, 1, 1); opacity: 1; height: 47px;">
                <fieldset class="filepond--file-wrapper">
                    <legend>file.docx</legend>
                    <div class="filepond--file">
                        <button class="filepond--file-action-button filepond--action-abort-item-load" type="button" data-align="right" disabled="disabled" style="transform: translate3d(0px, 0px, 0px) scale3d(1, 1, 1); opacity: 0; visibility: hidden; pointer-events: none;"><span>Megszakítás</span></button><button class="filepond--file-action-button filepond--action-retry-item-load" type="button" data-align="right" disabled="disabled" style="transform: translate3d(0px, 0px, 0px) scale3d(1, 1, 1); opacity: 0; visibility: hidden; pointer-events: none;"><svg width="26" height="26" viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg"><path d="M10.81 9.185l-.038.02A4.997 4.997 0 0 0 8 13.683a5 5 0 0 0 5 5 5 5 0 0 0 5-5 1 1 0 0 1 2 0A7 7 0 1 1 9.722 7.496l-.842-.21a.999.999 0 1 1 .484-1.94l3.23.806c.535.133.86.675.73 1.21l-.804 3.233a.997.997 0 0 1-1.21.73.997.997 0 0 1-.73-1.21l.23-.928v-.002z" fill="currentColor" fill-rule="nonzero"></path></svg><span>Újrapróbálkozás</span></button><button class="filepond--file-action-button filepond--action-remove-item" type="button" data-align="left" style="transform: translate3d(0px, 0px, 0px) scale3d(1, 1, 1); opacity: 1;"><svg width="26" height="26" viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg"><path d="M11.586 13l-2.293 2.293a1 1 0 0 0 1.414 1.414L13 14.414l2.293 2.293a1 1 0 0 0 1.414-1.414L14.414 13l2.293-2.293a1 1 0 0 0-1.414-1.414L13 11.586l-2.293-2.293a1 1 0 0 0-1.414 1.414L11.586 13z" fill="currentColor" fill-rule="nonzero"></path></svg><span>Eltávolítás</span></button><button class="filepond--file-action-button filepond--action-process-item" type="button" data-align="right" disabled="disabled" style="transform: translate3d(0px, 0px, 0px) scale3d(1, 1, 1); opacity: 0; visibility: hidden; pointer-events: none;"><svg width="26" height="26" viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg"><path d="M14 10.414v3.585a1 1 0 0 1-2 0v-3.585l-1.293 1.293a1 1 0 0 1-1.414-1.415l3-3a1 1 0 0 1 1.414 0l3 3a1 1 0 0 1-1.414 1.415L14 10.414zM9 18a1 1 0 0 1 0-2h8a1 1 0 0 1 0 2H9z" fill="currentColor" fill-rule="evenodd"></path></svg><span>Feltöltés</span></button><button class="filepond--file-action-button filepond--action-abort-item-processing" type="button" data-align="right" disabled="disabled" style="transform: translate3d(0px, 0px, 0px) scale3d(1, 1, 1); opacity: 0; visibility: hidden; pointer-events: none;"><span>Megszakítás</span></button><button class="filepond--file-action-button filepond--action-retry-item-processing" type="button" data-align="right" disabled="disabled" style="transform: translate3d(0px, 0px, 0px) scale3d(1, 1, 1); opacity: 0; visibility: hidden; pointer-events: none;"><svg width="26" height="26" viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg"><path d="M10.81 9.185l-.038.02A4.997 4.997 0 0 0 8 13.683a5 5 0 0 0 5 5 5 5 0 0 0 5-5 1 1 0 0 1 2 0A7 7 0 1 1 9.722 7.496l-.842-.21a.999.999 0 1 1 .484-1.94l3.23.806c.535.133.86.675.73 1.21l-.804 3.233a.997.997 0 0 1-1.21.73.997.997 0 0 1-.73-1.21l.23-.928v-.002z" fill="currentColor" fill-rule="nonzero"></path></svg><span>Újrapróbálkozás</span></button><button class="filepond--file-action-button filepond--action-revert-item-processing" type="button" data-align="right" disabled="disabled" style="transform: translate3d(0px, 0px, 0px) scale3d(1, 1, 1); opacity: 0; visibility: hidden; pointer-events: none;"><svg width="26" height="26" viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg"><path d="M11.586 13l-2.293 2.293a1 1 0 0 0 1.414 1.414L13 14.414l2.293 2.293a1 1 0 0 0 1.414-1.414L14.414 13l2.293-2.293a1 1 0 0 0-1.414-1.414L13 11.586l-2.293-2.293a1 1 0 0 0-1.414 1.414L11.586 13z" fill="currentColor" fill-rule="nonzero"></path></svg><span>Eltávolítás</span></button>
                        <div class="filepond--processing-complete-indicator" data-align="right"
                            style="transform: scale3d(0.75, 0.75, 1); opacity: 0; visibility: hidden; pointer-events: none;">
                            <svg width="26" height="26" viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg">
                                <path
                                    d="M18.293 9.293a1 1 0 0 1 1.414 1.414l-7.002 7a1 1 0 0 1-1.414 0l-3.998-4a1 1 0 1 1 1.414-1.414L12 15.586l6.294-6.293z"
                                    fill="currentColor" fill-rule="nonzero"></path>
                            </svg></div>
                        <div class="filepond--file-info" style="transform: translate3d(35px, 0px, 0px);">
                            <span class="filepond--file-info-main" aria-hidden="true"><a class="filepond--download-icon" href="REMOVED" download="file.docx"></a>file.docx</span><span class="filepond--file-info-sub">34 KB</span>
                        </div>
                        <div class="filepond--file-status"
                            style="transform: translate3d(35px, 0px, 0px); opacity: 0; visibility: hidden; pointer-events: none;">
                            <span class="filepond--file-status-main"></span><span class="filepond--file-status-sub"></span>
                        </div>
                        <div class="filepond--progress-indicator filepond--load-indicator"
                            style="opacity: 0; visibility: hidden; pointer-events: none;"><svg>
                                <path stroke-width="2" stroke-linecap="round"></path>
                            </svg></div>
                        <div class="filepond--progress-indicator filepond--process-indicator"
                            style="opacity: 0; visibility: hidden; pointer-events: none;"><svg>
                                <path stroke-width="2" stroke-linecap="round"></path>
                            </svg></div>
                    </div>
                </fieldset>
                <div class="filepond--panel filepond--item-panel" data-scalable="true">
                    <div class="filepond--panel-top filepond--item-panel"></div>
                    <div class="filepond--panel-center filepond--item-panel"
                        style="transform: translate3d(0px, 8px, 0px) scale3d(1, 0.31, 1);"></div>
                    <div class="filepond--panel-bottom filepond--item-panel"
                        style="transform: translate3d(0px, 39px, 0px);"></div>
                </div>
            </li>
        </ul>
    </div>
    <div class="filepond--panel filepond--panel-root" data-scalable="true">
        <div class="filepond--panel-top filepond--panel-root"></div>
        <div class="filepond--panel-center filepond--panel-root"
            style="transform: translate3d(0px, 8px, 0px) scale3d(1, 0.6, 1);"></div>
        <div class="filepond--panel-bottom filepond--panel-root" style="transform: translate3d(0px, 68px, 0px);"></div>
    </div>
    <span class="filepond--assistant" id="filepond--assistant-avj6z91jj" role="alert" aria-live="polite" aria-relevant="additions"></span>
    <div class="filepond--drip"></div>
    <fieldset class="filepond--data">
        <legend>Files</legend><input type="hidden" name="filepond" value="REMOVED">
    </fieldset>
</div>

k3rielit avatar Sep 09 '25 10:09 k3rielit

@k3rielit your issue is unrelated and should be fixed by #16900 (you can backport it to v3 via a PR once it is merged into v4)

That is a different issue, where the fileupload field overflows onto other components, but in this case the drop label is above every other control inside the filepond root so files cannot be downloaded, removed, etc.

Hiding the overflow of the filepond root element does not fix this issue.

k3rielit avatar Sep 09 '25 10:09 k3rielit

My temporary fix is applying this style via a userscript or a style editor extension:

.fi-fo-repeater >* .fi-fo-repeater-item > .fi-fo-repeater-item-content >* .filepond--drop-label {
    background: rgba(0,0,0,0.5);
    height: 20px !important;
    display: block;
    position: relative;
    top: 0;
    left: 60%;
    width: 200px;
}

This makes the drop area smaller and moves it to the right.

k3rielit avatar Sep 10 '25 13:09 k3rielit