I am trying to create a filter setup that I can add to a Material-UI dropdown that I can pass via props of what specified value of specified variable so I can reused the filter on any of my dropdowns, so I can declare different variable and different values for each.
The API used to populate the Dropdown is returning a value set similar to this:
0: {id: 7, name: 'Time', isOnHold: 0}
1: {id: 8, name: 'Temperature', isOnHold: 1}
I would like to pass the variable as filterVar
, and the value of that variable as filterVal
so I can select different variable for different dropdowns. In the example below I want to filter out options where isOnHold = 1
.
Here is what I have attempted:
As called from the form:
<Dropdown
onChange={handleInputChange}
label='Parameter'
name='parameterId'
value={values.parameterId}
prompt='Select A Parameter...'
url={paramUrl}
filterVar={'isOnHold'}
filterVal={1}
/>
The Dropdown component:
import * as React from 'react';
import axios from 'axios';
import { FormControl, FormHelperText, InputLabel, Select, MenuItem } from '@material-ui/core';
function Dropdown(props) {
const { filterVar, filterVal, label, name, onChange, prompt, value, url, ...other } = props;
const [options, setOptions] = React.useState([]);
React.useEffect(() => {
const fetchData = async () => {
const res = await axios.get(url);
setOptions(res.data);
};
fetchData();
}, []);
return(
<FormControl >
<InputLabel>{label}</InputLabel>
<Select
onChange={onChange}
value={value}
name={name}
{...other}
>
<MenuItem>{prompt}</MenuItem>
{options.filter(option => (option.filterVar).includes(filterVal)).map((option, id) => (
<MenuItem
key={option.id}
value={option.id}
>
{option.name}
</MenuItem>
))}
</Select>
</FormControl>
);
}
export default Dropdown;
As it right now, I can't get this to work, I keep getting an error of:
Uncaught TypeError: Cannot read properties of undefined (reading 'includes')
, so if anyone know how I can fix this, or had a better want to handle filtering the options, it would be greatly appreciated. Something likes passing option.isOnHold === 1
.
Since you are sending the property name to the filterVar
variable, you should use the property accessor with the Bracket notation ([<property name>]
) instead of Dot notation as filterVar
is not the property in the option
object.
Also note that from your attached data, the isOnHold
is an integer instead of string. Hence, you should not use includes
as it is a String function; instead, use the equal operator ===
. Otherwise, you need to cast/convert isOnHold
to string.
Note that the <String>.includes("<substring>")
should be used when checking the string value contains the substring.
{options
.filter((option) => option[filterVar] === filterVal)
.map((option, id) => (
<MenuItem key={option.id} value={option.id}>
{option.name}
</MenuItem>
))}
Or
{options
.filter((option) => option[filterVar].toString().includes(filterVal))
.map((option, id) => (
<MenuItem key={option.id} value={option.id}>
{option.name}
</MenuItem>
))}