Reputation: 145
I am trying to create a reusable dropdown for using in a React edit form. Currently you select a record from the table to edit, which opens a modal with the edit form. The current values in the edit form are populated from the current values pulled together in an API, not the full item record. I am doing the Axios call and setting the options all within the dropdown component, so all I have to do is pass the URL of the API via props for each dropdown. Eventually I will have forms with multiple dropdowns, so I figured this was the easiest way to accomplish this.
Here is my situation, with examples of the data:
"name": "Tools",
"id": "1",
"name": "23456",
"description": "New Location",
"departmentName": "Tools"
"name": "23456",
"description": "New Location",
"departmentOther": {
"id": 1
}
Currently, I can populate the dropdown with a list of departments, display the current value of departmentName, and select a new value. As long as I use value={option.name} as the value of my menu items. If I use value={option.value} the dropdown displays an empty string as the current value. How can I take the values provided from the selected record and the dropdown list and supply the JSON needed for the PUT request?
I am also receiving this warning, since it doesn't seem to be comparing the current value to the options and seeing a matching value despite there being one:
You have provided an out-of-range value Tools
for the select (name="departmentName") component.'
Here is my code:
Component as used in form
<Controls.Dropdown
// onChange={handleInputChange}
label='Department'
name='departmentName'
prompt='Select A Department...'
url='/api/maintain/departments/'
value={values.departmentName}
/>
OnChange Function
const [values, setValues] = React.useState({} as any);
const handleInputChange = e => {
const { name, value } = e.target;
setValues({
...values,
[name]: ( typeof value === 'string' ? (value).replace(/ +(?= )/g, '').trimStart() : value ) // removes leading space & multiple spaces if value is a string
});
if (validateOnChange)
{ validate({ [name]: value }); }
};
Dropdown
export default function Dropdown(props) {
const { error = null, label, onChange, prompt, value, url, ...other } = props;
const [departmentId, setDepartmentId] = React.useState(null);
const [options, setOptions] = React.useState([]);
const dropdownUrl = environment.originURL + environment.apiUrl + url;
// Fetch Data for Dropdown list
React.useEffect(() => {
const fetchData = async () => {
const res = await axios.get(dropdownUrl);
setOptions( res.data );
};
fetchData();
}, [setOptions]);
// Dropdown List
return(
<>
<FormControl className={classes.formControl} variant='outlined' >
<InputLabel>{label}</InputLabel>
<Select
defaultValue=''
// onChange={onChange}
onChange={(e) => {
const { value } = e.target;
value={value === undefined || null ? '' : value}
// value={departmentId}
onChange(value);
}}
value={value}
{...other}
{...(error && {error: true, helperText: error})}
>
<MenuItem>{prompt}</MenuItem>
{options.map((option, id) => (
<MenuItem
key={option.id}
value={option.value}
// value={option.value}
>
{option.name}
</MenuItem>
))}
</Select>
</FormControl>
</>
);
}
Upvotes: 0
Views: 2098
Reputation: 66
You can get the department Id as well. First you have to make a state for it and then whenever a new item is clicked/changed, you need to update the state as well. Here is the updated code for Dropdown.
// Dropdown
export default function Dropdown(props) {
const { error = null, label, onChange, prompt, value, url, ...other } = props;
const [options, setOptions] = React.useState([]);
const [departmentId, setDepartmentId] = React.useState(null);
const dropdownUrl = environment.originURL + environment.apiUrl + url;
// Fetch Data for Dropdown list
React.useEffect(() => {
const fetchData = async () => {
const res = await axios.get(dropdownUrl);
setOptions( res.data );
};
fetchData();
}, [setOptions]);
// Dropdown List
return(
<>
<FormControl className={classes.formControl} variant='outlined' >
<InputLabel>{label}</InputLabel>
<Select
defaultValue=''
onChange={(e) => {
const { value } = e.target;
setDepartmentId(value);
onChange(value);
}}
value={departmentId}
{...other}
{...(error && {error: true, helperText: error})}
>
<MenuItem>{prompt}</MenuItem>
{options.map((option, id) => (
<MenuItem
key={option.id}
value={option.value}
>
{option.name}
</MenuItem>
))}
</Select>
</FormControl>
</>
);
}
And i think it should work now.
Upvotes: 0