25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

90 lines
2.6 KiB

  1. import { Autocomplete, TextField } from '@mui/material';
  2. import { useEffect, useState } from 'react';
  3. export default function Combo({
  4. valueName,
  5. disabled,
  6. form,
  7. dataList = [],
  8. filterOptions,
  9. getOptionLabel,
  10. isOptionEqualToValue,
  11. onInputChange,
  12. onChange,
  13. ...props
  14. }) {
  15. const formValue = form.values[valueName] ?? null;
  16. const [inputValue, setInputValue] = useState("");
  17. // optional: keep input text in sync when form value changes (e.g. after reload/reset)
  18. useEffect(() => {
  19. if (!formValue) return;
  20. try {
  21. const label = getOptionLabel ? getOptionLabel(formValue) : "";
  22. if (typeof label === "string") setInputValue(label);
  23. } catch {
  24. // ignore label errors
  25. }
  26. // eslint-disable-next-line react-hooks/exhaustive-deps
  27. }, [formValue]);
  28. const defaultIsEqual = (option, value) => option?.id != null && value?.id != null
  29. ? option.id === value.id
  30. : option === value;
  31. return (
  32. <Autocomplete
  33. {...props}
  34. disablePortal
  35. fullWidth
  36. id={valueName}
  37. disabled={disabled}
  38. // consider removing disableClearable if you allow empty
  39. disableClearable
  40. options={Array.isArray(dataList) ? dataList : []}
  41. value={formValue}
  42. inputValue={inputValue}
  43. filterOptions={filterOptions}
  44. getOptionLabel={(opt) => {
  45. if (!opt) return "";
  46. const v = getOptionLabel ? getOptionLabel(opt) : String(opt);
  47. return typeof v === "string" ? v : "";
  48. }}
  49. isOptionEqualToValue={(option, value) => {
  50. return isOptionEqualToValue
  51. ? isOptionEqualToValue(option, value)
  52. : defaultIsEqual(option, value);
  53. }}
  54. onInputChange={(event, newValue) => {
  55. if (onInputChange) onInputChange(event, newValue, setInputValue);
  56. else setInputValue(newValue);
  57. }}
  58. onChange={(event, newValue) => {
  59. if (onChange) onChange(event, newValue);
  60. else form.setFieldValue(valueName, newValue);
  61. }}
  62. sx={{
  63. '& .MuiInputBase-root': { alignItems: 'center' },
  64. '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' },
  65. '& .MuiOutlinedInput-root': { height: 40 },
  66. "& .MuiInputBase-input.Mui-disabled": {
  67. WebkitTextFillColor: "#000000",
  68. background: "#f8f8f8",
  69. },
  70. }}
  71. renderInput={(params) => (
  72. <TextField
  73. {...params}
  74. sx={{
  75. "& .MuiInputBase-input.Mui-disabled": {
  76. WebkitTextFillColor: "#000000",
  77. background: "#f8f8f8",
  78. },
  79. }}
  80. />
  81. )}
  82. />
  83. );
  84. }