Skip to content

Customize FileWidget. #3146

@uk-taniyama

Description

@uk-taniyama

Prerequisites

What theme are you using?

core

Is your feature request related to a problem? Please describe.

I want to change only the file input button.
like follows.

<label><input ...><button>File</button></label>

But now I have to copy and modify all sources.

Describe the solution you'd like

No response

Describe alternatives you've considered

packages/core/src/components/widgets/FileWidget.tsx

  • Export type FileInfoType
  • Export function FilesInfo
  • Extract FileWidget handling into useFileWidget .
export interface UseFileWidgetParams {
  multiple?: boolean;
  value: any;
  onChange: (value: any) => void;
}

export interface UseFileWidgetResult {
  filesInfo: FileInfoType[]
  handleChange: (event: ChangeEvent<HTMLInputElement>) => void;
}

export function useFileWidget({
  multiple,
  value,
  onChange,
}: UseFileWidgetParams): UseFileWidgetResult {
  const extractedFilesInfo = useMemo(
    () =>
      Array.isArray(value) ? extractFileInfo(value) : extractFileInfo([value]),
    [value]
  );
  const [filesInfo, setFilesInfo] = useState<FileInfoType[]>(extractedFilesInfo);

  const handleChange = useCallback(
    (event: ChangeEvent<HTMLInputElement>) => {
      if (!event.target.files) {
        return;
      }
      processFiles(event.target.files).then((filesInfoEvent) => {
        setFilesInfo(filesInfoEvent);
        const newValue = filesInfoEvent.map((fileInfo) => fileInfo.dataURL);
        if (multiple) {
          onChange(newValue);
        } else {
          onChange(newValue[0]);
        }
      });
    },
    [multiple, onChange]
  );
  return { filesInfo, handleChange };
}

/**
 *  The `FileWidget` is a widget for rendering file upload fields.
 *  It is typically used with a string property with data-url format.
 */
function FileWidget<T, F>({
  multiple,
  id,
  readonly,
  disabled,
  onChange,
  value,
  autofocus = false,
  options,
}: WidgetProps<T, F>) {
  const { filesInfo, handleChange } = useFileWidget({ multiple, value, onChange }); 

  return (
    <div>
      <p>
        <input
          id={id}
          type="file"
          disabled={readonly || disabled}
          onChange={handleChange}
          defaultValue=""
          autoFocus={autofocus}
          multiple={multiple}
          accept={options.accept ? String(options.accept) : undefined}
        />
      </p>
      <FilesInfo filesInfo={filesInfo} />
    </div>
  );
}

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions