Skip to content

Commit

Permalink
Fix drag and drop native input required validation error
Browse files Browse the repository at this point in the history
  • Loading branch information
indigane committed Sep 5, 2024
1 parent dd673c7 commit 98098d6
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 24 deletions.
19 changes: 1 addition & 18 deletions frontend/src/common/components/GenericDocumentsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Button, Fieldset, IconArrowLeft, IconCrossCircle, IconDocument, IconPlus, StatusLabel} from "hds-react";
import {useCallback, useRef, useState} from "react";
import {useCallback, useState} from "react";
import {SubmitHandler, useFieldArray, useForm, useFormContext} from "react-hook-form";
import {IApartmentDetails, IHousingCompanyDetails} from "../schemas";
import {FileInput, FormProviderForm, TextInput} from "./forms";
Expand Down Expand Up @@ -98,14 +98,12 @@ const DocumentRemoveLineButton = ({name, index, remove}) => {
const DocumentsListItems = ({name, remove}) => {
const formObject = useFormContext();
const documents = formObject.watch(name);
const documentListItemRef = useRef(null);
return (
<>
{documents.map((document, index) => (
<li
className="documents-list-item"
key={`document-item-${document.id ?? document.key}`}
ref={documentListItemRef}
>
<TextInput
label="Nimi"
Expand All @@ -119,21 +117,6 @@ const DocumentsListItems = ({name, remove}) => {
document.file_link || document.file_object ? "Vaihda tiedosto" : "Valitse tiedosto"
}
name={`${name}.${index}.file_object`}
onChange={(filesArray) => {
// File is a required field but the HDS file input clears the native input after selection so the form is always invalid.
// This is a hack to make sure the native input has a file if the user has selected one so that the form can be submitted.
const documentListItem = documentListItemRef.current as HTMLElement | null;
const fileInput = documentListItem?.querySelector(
'input[type="file"]'
) as HTMLInputElement | null;
if (fileInput) {
const datatransfer = new DataTransfer();
datatransfer.items.add(filesArray[0]);
setTimeout(() => (fileInput.files = datatransfer.files), 10);
}
// Explicitly mark as dirty, since react-hook-form does not support File objects for dirty checking.
formObject.setValue(`${name}.${index}.file_object`, filesArray[0], {shouldDirty: true});
}}
required={!document.file_link}
defaultValue={document.file_object ? [document.file_object] : []}
/>
Expand Down
25 changes: 19 additions & 6 deletions frontend/src/common/components/forms/FileInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {FileInput as HDSFileInput} from "hds-react";

import React from "react";
import React, {useRef} from "react";
import {useFormContext} from "react-hook-form";
import {FormInputProps} from "./";

Expand All @@ -10,22 +10,35 @@ interface FileInputProps extends FormInputProps {
}
const FileInput = ({name, label = "", required, onChange, ...rest}: FileInputProps): React.JSX.Element => {
const formObject = useFormContext();
const containerRef = useRef(null);

const {
register,
formState: {errors},
} = formObject;
register(name, {required: required});

const handleChange = (e) => {
// Set the value of the input to the file selected
formObject.setValue(name, e[0]);
const handleChange = (filesArray) => {
// File is a required field but the HDS file input clears the native input after selection so the form is always invalid.
// This is a hack to make sure the native input has a file if the user has selected one so that the form can be submitted.
const containerElement = containerRef.current as HTMLElement | null;
const fileInput = containerElement?.querySelector('input[type="file"]') as HTMLInputElement | null;
if (fileInput) {
const datatransfer = new DataTransfer();
datatransfer.items.add(filesArray[0]);
setTimeout(() => (fileInput.files = datatransfer.files), 10);
}
// Explicitly mark as dirty, since react-hook-form does not support File objects for dirty checking.
formObject.setValue(name, filesArray[0], {shouldDirty: true});
// If there is an onChange handler, call it
onChange && onChange(e);
onChange && onChange(filesArray);
};

return (
<div className="input-field--file">
<div
ref={containerRef}
className="input-field--file"
>
<HDSFileInput
id={name}
label={label}
Expand Down

0 comments on commit 98098d6

Please sign in to comment.