From f5a4a14debac5f170fa7146e30bdf364ea55c2b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rui=20Ara=C3=BAjo?= Date: Sat, 10 Aug 2024 16:54:54 +0100 Subject: [PATCH] feat(autocomplete): pre select option (if any option matching the value was found) --- src/components/AutocompleteController.tsx | 131 ++++++++++++---------- 1 file changed, 74 insertions(+), 57 deletions(-) diff --git a/src/components/AutocompleteController.tsx b/src/components/AutocompleteController.tsx index d981146..62f0967 100644 --- a/src/components/AutocompleteController.tsx +++ b/src/components/AutocompleteController.tsx @@ -1,12 +1,12 @@ import { Autocomplete, CircularProgress, TextField } from '@mui/material'; -import { Controller } from 'react-hook-form'; +import { Controller, useController } from 'react-hook-form'; import { useAsyncFieldControllerLabels, useFieldControllerLabels, useFieldControllerWithOptionsLabels, useOnErrorMessage, } from '../hooks/index'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import type { AsyncFieldControllerProps, FieldControllerProps, @@ -87,67 +87,84 @@ export const AutocompleteController = < FreeSolo > | null>(initialValue ?? null); + const { + field: { onChange, value, ...other }, + fieldState: { invalid, error }, + } = useController({ + name, + control, + }); + + /** + * Side effects + */ + useEffect(() => { + if (value) { + const optionFound = options.find((option) => optionValueAccessor(option) === value); + if (optionFound) { + setSelectedValue(optionFound as AutocompleteValue | null); + } + } + }, [value]); + + /** + * Render + */ return ( - ( - { - if (!value) { - return ''; - } else if (getOptionLabel) { - return getOptionLabel(value); - } + { + if (!value) { + return ''; + } else if (getOptionLabel) { + return getOptionLabel(value); + } - return ''; - }} - isOptionEqualToValue={(option, value) => { - if (!value) { - return false; - } else if (isOptionEqualToValue) { - return isOptionEqualToValue(option, value); - } + return ''; + }} + isOptionEqualToValue={(option, value) => { + if (!value) { + return false; + } else if (isOptionEqualToValue) { + return isOptionEqualToValue(option, value); + } - return false; - }} - loading={loading} - loadingText={fieldControllerLoadingLabel} - noOptionsText={loadingError ? fieldControllerLoadingErrorLabel : fieldControllerNoOptionsLabel} - onChange={(_: unknown, newValue) => { - setSelectedValue(newValue ?? null); - onChange(optionValueAccessor(newValue)); + return false; + }} + loading={loading} + loadingText={fieldControllerLoadingLabel} + noOptionsText={loadingError ? fieldControllerLoadingErrorLabel : fieldControllerNoOptionsLabel} + onChange={(_: unknown, newValue) => { + setSelectedValue(newValue ?? null); + onChange(optionValueAccessor(newValue)); + }} + options={options ?? []} + renderInput={(params) => ( + + {loading ? ( + + ) : null} + {params.InputProps.endAdornment} + + ), }} - options={options ?? []} - renderInput={(params) => ( - - {loading ? ( - - ) : null} - {params.InputProps.endAdornment} - - ), - }} - {...muiProps?.textField} - error={invalid} - helperText={error?.message ? fieldOnErrorMessage(error?.message) : null} - label={fieldControllerLabel} - /> - )} - value={selectedValue as AutocompleteValue} - {...autocompleteProps} + {...muiProps?.textField} + error={invalid} + helperText={error?.message ? fieldOnErrorMessage(error?.message) : null} + label={fieldControllerLabel} /> )} + value={selectedValue as AutocompleteValue} + {...autocompleteProps} /> ); };