Files
automatisch/packages/web/src/components/ControlledAutocomplete/index.tsx
2022-10-09 00:00:35 +02:00

74 lines
2.5 KiB
TypeScript

import * as React from 'react';
import FormHelperText from '@mui/material/FormHelperText';
import { Controller, useFormContext } from 'react-hook-form';
import Autocomplete, { AutocompleteProps } from '@mui/material/Autocomplete';
import type { IFieldDropdownOption } from '@automatisch/types';
interface ControlledAutocompleteProps extends AutocompleteProps<IFieldDropdownOption, boolean, boolean, boolean> {
shouldUnregister?: boolean;
name: string;
required?: boolean;
description?: string;
}
const getOption = (options: readonly IFieldDropdownOption[], value: string) => options.find(option => option.value === value) || null;
function ControlledAutocomplete(props: ControlledAutocompleteProps): React.ReactElement {
const { control } = useFormContext();
const {
required = false,
name,
defaultValue,
shouldUnregister,
onBlur,
onChange,
description,
options = [],
...autocompleteProps
} = props;
return (
<Controller
rules={{ required }}
name={name}
defaultValue={defaultValue || ''}
control={control}
shouldUnregister={shouldUnregister}
render={({ field: { ref, onChange: controllerOnChange, onBlur: controllerOnBlur, ...field }, fieldState }) => (
<div>
{/* encapsulated with an element such as div to vertical spacing delegated from parent */}
<Autocomplete
{...autocompleteProps}
{...field}
options={options}
value={getOption(options, field.value)}
onChange={(event, selectedOption, reason, details) => {
const typedSelectedOption = selectedOption as IFieldDropdownOption;
if (typedSelectedOption !== null && Object.prototype.hasOwnProperty.call(typedSelectedOption, 'value')) {
controllerOnChange(typedSelectedOption.value);
} else {
controllerOnChange(typedSelectedOption);
}
onChange?.(event, selectedOption, reason, details);
}}
onBlur={(...args) => { controllerOnBlur(); onBlur?.(...args); }}
ref={ref}
data-test={`${name}-autocomplete`}
/>
<FormHelperText
variant="outlined"
error={Boolean(fieldState.isTouched && fieldState.error)}
>
{fieldState.isTouched ? fieldState.error?.message || description : description}
</FormHelperText>
</div>
)}
/>
);
}
export default ControlledAutocomplete;