Mtullis
Mtullis

Reputation: 145

Selecting and using values from API populated dropdown in a React form

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

Answers (1)

Itezaz
Itezaz

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

Related Questions