diff --git a/changelog/fix-460-file-upload-does-not-start-selecting-same-file b/changelog/fix-460-file-upload-does-not-start-selecting-same-file new file mode 100644 index 00000000000..3311dcdf4d1 --- /dev/null +++ b/changelog/fix-460-file-upload-does-not-start-selecting-same-file @@ -0,0 +1,4 @@ +Significance: patch +Type: fix + +Empty file input to allow the user to select the same file again if there's an error. diff --git a/client/components/file-upload/index.tsx b/client/components/file-upload/index.tsx index 4b9e2ef9990..ab637aa10d8 100644 --- a/client/components/file-upload/index.tsx +++ b/client/components/file-upload/index.tsx @@ -41,6 +41,29 @@ export const FileUploadControl = ( { /> ); + const handleButtonClick = ( + event: React.MouseEvent< HTMLButtonElement >, + openFileDialog: () => void + ) => { + // Get file input next to the button element and clear it's value, + // allowing to select the same file again in case of + // connection or general error or just need to select it again. + // This workaround is useful until we update @wordpress/components to a + // version the supports this: https://github.com/WordPress/gutenberg/issues/39267 + const fileInput: + | HTMLInputElement + | null + | undefined = ( event.target as HTMLButtonElement ) + .closest( '.components-form-file-upload' ) + ?.querySelector( 'input[type="file"]' ); + + if ( fileInput ) { + fileInput.value = ''; + } + + openFileDialog(); + }; + return (
@@ -72,9 +88,25 @@ export const FileUploadControl = ( { ( event.target.files || new FileList() )[ 0 ] ); } } - > - { __( 'Upload file', 'woocommerce-payments' ) } - + render={ ( { openFileDialog } ) => ( + + ) } + > { hasError ? ( diff --git a/client/components/file-upload/test/index.tsx b/client/components/file-upload/test/index.tsx index a25482ab1d0..ad0cbcb243a 100644 --- a/client/components/file-upload/test/index.tsx +++ b/client/components/file-upload/test/index.tsx @@ -5,6 +5,7 @@ */ import * as React from 'react'; import { render, fireEvent } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; /** * Internal dependencies @@ -87,6 +88,29 @@ describe( 'FileUploadControl', () => { ); } ); + test( 'triggers onFileChange two times when selecting the same file again', async () => { + const { container: control } = render( + + ); + + const file = new File( [ 'hello' ], 'hello.png', { + type: 'image/png', + } ); + + // Note: FormFileUpload does not associate file input with label so workaround is required to select it. + const input = control.querySelector( 'input[type="file"]' ); + if ( input !== null ) { + await userEvent.upload( input, file ); + await userEvent.upload( input, file ); + } + + expect( props.onFileChange ).toHaveBeenNthCalledWith( + 2, + field.key, + file + ); + } ); + test( 'triggers onFileRemove', () => { props.fileName = 'file.pdf'; props.isDone = true;