Skip to content

Commit ae3f2b3

Browse files
Allow to reset FileInputField internal state by calling resetState function on its ref (#630)
1 parent 00d2897 commit ae3f2b3

File tree

2 files changed

+63
-12
lines changed

2 files changed

+63
-12
lines changed

src/components/FileInputField/FileInputField.jsx

+25-12
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,38 @@ export const FileInputField = React.forwardRef((props, ref) => {
3737
...restProps
3838
} = props;
3939

40-
const internalInputRef = useRef();
41-
42-
// We need to have a reference to the input element to be able to call its methods,
43-
// but at the same time we want to expose this reference to the parent component for
44-
// case someone wants to call input methods from outside the component.
45-
useImperativeHandle(ref, () => internalInputRef.current);
46-
4740
const formLayoutContext = useContext(FormLayoutContext);
4841
const inputGroupContext = useContext(InputGroupContext);
4942
const translations = useContext(TranslationsContext);
5043

5144
const [selectedFileNames, setSelectedFileNames] = useState([]);
5245
const [isDragging, setIsDragging] = useState(false);
5346

47+
const internalInputRef = useRef();
48+
49+
const handleReset = useCallback((event) => {
50+
setSelectedFileNames([]);
51+
onFilesChanged([], event);
52+
}, [onFilesChanged]);
53+
54+
// We need to have a reference to the input element to be able to call its methods,
55+
// but at the same time we want to expose this reference to the parent component in
56+
// case someone wants to call input methods from outside the component.
57+
useImperativeHandle(
58+
ref,
59+
() => {
60+
// The reason of extending object instead of using spread operator is that
61+
// if it is transformed to the object, it changes the reference of the object
62+
// and its prototype chain.
63+
const inputEl = internalInputRef?.current ?? {};
64+
inputEl.resetState = () => {
65+
handleReset(null);
66+
};
67+
return inputEl;
68+
},
69+
[handleReset],
70+
);
71+
5472
const handleFileChange = (files, event) => {
5573
if (files.length === 0) {
5674
setSelectedFileNames([]);
@@ -101,11 +119,6 @@ export const FileInputField = React.forwardRef((props, ref) => {
101119
}
102120
};
103121

104-
const handleReset = useCallback((event) => {
105-
setSelectedFileNames([]);
106-
onFilesChanged([], event);
107-
}, [onFilesChanged]);
108-
109122
useEffect(() => {
110123
const inputEl = internalInputRef.current;
111124
if (!inputEl) {

src/components/FileInputField/README.md

+38
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,44 @@ set the `multiple` prop to `true`.
236236
/>
237237
```
238238

239+
## Resetting Input State
240+
241+
If you need to reset the input state, you can do it by calling the
242+
`resetState` method on the component's ref.
243+
244+
```docoff-react-preview
245+
React.createElement(() => {
246+
const fileInputRef = React.useRef();
247+
248+
return (
249+
<Toolbar align="bottom">
250+
<ToolbarItem>
251+
<FileInputField
252+
id="my-file"
253+
label="Attachment"
254+
onFilesChanged={() => {}}
255+
ref={fileInputRef}
256+
/>
257+
</ToolbarItem>
258+
<ToolbarItem>
259+
<Button
260+
label="Reset file input state"
261+
onClick={() => {
262+
if (!fileInputRef.current) {
263+
return;
264+
}
265+
fileInputRef.current.resetState();
266+
}}
267+
/>
268+
</ToolbarItem>
269+
</Toolbar>
270+
);
271+
});
272+
```
273+
274+
You can also reset the input state by clicking the button with the `reset` type
275+
inside a form.
276+
239277
## Forwarding HTML Attributes
240278

241279
In addition to the options below in the [component's API](#api) section, you

0 commit comments

Comments
 (0)