Use forwardRef in FileInput

Committed-by: Rene Pfeuffer <rene.pfeuffer@cloudogu.com>
This commit is contained in:
Florian Scholdei
2023-05-04 08:22:02 +02:00
parent ea67a04b5d
commit 05bc61ab1b
2 changed files with 55 additions and 64 deletions

View File

@@ -0,0 +1,2 @@
- type: fixed
description: Allow passing a ref through FileInput to one of its children

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import React, { ChangeEvent, FC, FocusEvent, useState } from "react";
import React, { ChangeEvent, FocusEvent, useState } from "react";
import { useTranslation } from "react-i18next";
import classNames from "classnames";
import { createAttributesForTesting } from "../devBuild";
@@ -39,77 +39,66 @@ type Props = {
testId?: string;
onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
onBlur?: (event: FocusEvent<HTMLInputElement>) => void;
ref?: React.Ref<HTMLInputElement>;
};
const FileInput: FC<Props> = ({
name,
filenamePlaceholder,
testId,
helpText,
placeholder,
disabled,
label,
className,
ref,
onBlur,
onChange,
}) => {
const [t] = useTranslation("commons");
const [file, setFile] = useState<File | null>(null);
const FileInput = React.forwardRef<HTMLInputElement, Props>(
({ name, filenamePlaceholder, testId, helpText, placeholder, disabled, label, className, onBlur, onChange }, ref) => {
const [t] = useTranslation("commons");
const [file, setFile] = useState<File | null>(null);
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
const uploadedFile = event?.target?.files![0];
// @ts-ignore the uploaded file doesn't match our types
setFile(uploadedFile);
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
const uploadedFile = event?.target?.files![0];
// @ts-ignore the uploaded file doesn't match our types
setFile(uploadedFile);
if (onChange && event.target.files) {
onChange(event);
}
};
if (onChange && event.target.files) {
onChange(event);
}
};
const handleBlur = (event: FocusEvent<HTMLInputElement>) => {
if (onBlur && event.target.files) {
onBlur(event);
}
};
const handleBlur = (event: FocusEvent<HTMLInputElement>) => {
if (onBlur && event.target.files) {
onBlur(event);
}
};
const id = createA11yId("file-input");
const id = createA11yId("file-input");
return (
<div className={classNames("field", className)}>
<LabelWithHelpIcon label={label} helpText={helpText} id={id} />
<div className="file is-info has-name is-fullwidth">
<label className="file-label">
<input
ref={ref}
name={name}
className="file-input"
type="file"
placeholder={placeholder}
disabled={disabled}
onChange={handleChange}
onBlur={handleBlur}
aria-describedby={id}
{...createAttributesForTesting(testId)}
/>
<span className="file-cta">
<span className="file-icon">
<i className="fas fa-arrow-circle-up" />
return (
<div className={classNames("field", className)}>
<LabelWithHelpIcon label={label} helpText={helpText} id={id} />
<div className="file is-info has-name is-fullwidth">
<label className="file-label">
<input
ref={ref}
name={name}
className="file-input"
type="file"
placeholder={placeholder}
disabled={disabled}
onChange={handleChange}
onBlur={handleBlur}
aria-describedby={id}
{...createAttributesForTesting(testId)}
/>
<span className="file-cta">
<span className="file-icon">
<i className="fas fa-arrow-circle-up" />
</span>
<span className="file-label has-text-weight-bold">{t("fileInput.label")}</span>
</span>
<span className="file-label has-text-weight-bold">{t("fileInput.label")}</span>
</span>
{file?.name ? (
<span className="file-name">{file?.name}</span>
) : (
<span className="file-name has-text-weight-light has-text-secondary">
{filenamePlaceholder || t("fileInput.noFileChosen")}
</span>
)}
</label>
{file?.name ? (
<span className="file-name">{file?.name}</span>
) : (
<span className="file-name has-text-weight-light has-text-secondary">
{filenamePlaceholder || t("fileInput.noFileChosen")}
</span>
)}
</label>
</div>
</div>
</div>
);
};
);
}
);
export default FileInput;