I am new to Material UI and have an issue. I have a reusable dropdown filter that is populated from an array. Everything works exactly how I want it to, but I keep getting a console error that the component is changing and uncontrolled input. The problem is, if I add a default value (value='') to eliminate the uncontrolled error, the dropdown will not display my selected filtering option in the input, just a blank. How can I control the component but still show my the user the filtering option selected.
const status = [
{id: 1, label: '...', value: ''},
{id: 2, label: 'Active', value: 48},
{id: 3, label: 'Inactive', value: -1},
{id: 4, label: 'On Hold', value: 48654},
{id: 5, label: 'Out Of Spec', value: 50989},
]
<DropdownFltr
prompt='Status...'
options={status}
onChange={handleFilterValue}
/>
export default function DropdownFltr(props) {
const { error=null, options, prompt, onChange, value, ...other } = props;
return(
<>
<FormControl>
<InputLabel>{prompt}</InputLabel>
<Select
value='' // <<< Causes issues, but fixed uncontrolled error
onChange={onChange}
{...other}
{...(error && {error:true, helperText:error})}
>
{options.map((option, id) => (
<MenuItem
key={option.id}
value={option.value}
>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
</>
)
}
Add the default Value in the Component Select
<Select
defaultValue={''}
/>
Related
I have a requirement to add tooltip on hover to disabled options in a dropdown in React fluent UI.
I am able to add tooltip to singular component using https://www.npmjs.com/package/#fluentui/react-tooltip
<Tooltipcontent="Example tooltip">
<Button/>
</Tooltip>
but how to add similar behaviour to dropdown options and only for disabled options
like: "Disabled cause of non avilability"
sample dropdown fluent ui code
const options: IDropdownOption[] = [
{ key: 'fruitsHeader', text: 'Fruits', itemType: DropdownMenuItemType.Header },
{ key: 'apple', text: 'Apple' },
{ key: 'banana', text: 'Banana' },
{ key: 'orange', text: 'Orange', disabled: true },
];
export const DropdownBasicExample: React.FunctionComponent = () => {
return (
<Stack tokens={stackTokens}>
<Dropdown
placeholder="Select an option"
label="Basic uncontrolled example"
options={options}
styles={dropdownStyles}
/>
</Stack>
);
};
Thanks
Fluent UI renders every disabled option as a button element with the disabled attribute, which makes it non-interactive by default.
Here's a method to solve this that I believe is also fairly accessible:
First, define your array of IDropdownOption items so that they conditionally set the disabled and title properties:
const options: IDropdownOption[] = [
{ key: 'apple', text: 'Apple' },
{ key: 'orange',
text: 'Orange',
disabled: isOrangeDisabled,
title: isOrangeDisabled ? "This is a disabled tooltip" : ""
},
];
You're also going to need to define a custom rendering function for the items in order to apply a nice tooltip:
<Dropdown onRenderOption={onRenderOption} />
and then define a function like this in your component:
const onRenderOption = (option: IDropdownOption): JSX.Element => {
return (
<>
{option?.disabled && (
<div className="interactive">
<TooltipHost content={option.title}>
<span>{option.text}</span>
</TooltipHost>
</div>
)}
{!option?.disabled && (
<span>{option.text}</span>
)}
</>
);
};
Finally, that interactive CSS class needs to be defined in your CSS file. This will override the browser's default behaviour of making disabled elements non-interactive:
.interactive {
pointer-events: auto;
}
Some things to note:
The reason the title is set to an empty string when the option is not disabled is so that it doesn't have a string value when the interactive item is rendered. Without this, the browser will render the tooltip when you hover on a selectable item, which looks ugly.
Using the title attribute should make the component pretty usable for screen readers and other assistive technology (though I am far from an expert)
The template only renders the TooltipHost and interactive class when the object is disabled, so that the tooltip and that behaviour only kick in when the option is disabled. Because the underlying option is still disabled, you still won't be able to select it.
I want to control the background color of checkbox but something is wrong.
first,
I have a data like
export const data = [
{id: 1, checked: true},
{id: 2, checked: false},
{id: 3, checked: false},
]
and a component got this data is like
import {data} from "./data"
(...)
{data.map(item => <label key={item.id}> <input type="checkbox" checked={item.checked}/> </label>}
when i was trying to change the background color of label,
i wrote code like this...
background: ${props => props.checked ? "#000" : "transparent"};
but this doesn't work well. the label has background color transparent only. how can i handle this??
in this case you could just use add style={{background: item.checked ? "#000" : 'transparent'}} to your label.
props refers to the values passed into a react component, in this case we're just using a regular label.
FYI - since you're hard-coding your data, your checkboxes won't be changeable - if thats something you need, you'll probably want to look at saving your data as a state, then modifying that based on the checkboxes being checked/unchecked.
const data = [
{id: 1, checked: false},
{id: 2, checked: true},
{id: 3, checked: false},
]
const element = (
<div>
{data.map( item => (
<label
key={item.id}
style={{background: item.checked ? "#000" : 'transparent'}}
>
<input type="checkbox" checked={item.checked} />
</label>
))}
</div>
);
ReactDOM.render(
element,
document.getElementById('root')
);
I'am creating drop down list for countries and its relevant country code. I want to set default value as '+xx' which is for particular country, but, its displayed as country as well as its respective code. How to hide country name, but, display only in drop down, i.e, country name as well as code.
Following is the code for reference
const countries = [
{
value: "US",
label: "+1"
},
{
value: "UK",
label: "+44"
},
{
value: "SA",
label: "+27"
},
{
value: "IND",
label: "+91"
}
];
const [countryCode, setCountryCode] = React.useState("+91");
const handleChange = (event) => {
setCountryCode(event.target.value);
};
return (
<TextField
id="standard-select-currency"
select
label="Select"
value={countryCode}
onChange={handleChange}
helperText="Please select your Country"
>
{countries.map((option) => (
<MenuItem key={option.value} value={option.label}>
<p>{option.label}</p>
<p>{option.value}</p>
</MenuItem>
))}
</TextField>
)
As you can see above in the image Country name is also seen which I want to hide. So, what is the best solution?
Below is the codesandbox link: https://codesandbox.io/s/material-demo-forked-kgkcd
You can use the Select component's renderValue prop to customize the displayed value. You can pass the select props to the TextField component through the SelectProps prop.
<TextField
select
label="Country Code"
value={countryCode}
onChange={handleChange}
SelectProps={{
renderValue: (value) => value,
}}
>
...
</TextField>
This is part of my code.
I am fetching drugs and hard-coding categories based on their class. Then I am mapping the categories, checking if a drug matches the category. If yes, then the MenuItem appears under the specific ListSubHeader.
useEffect(() => {
fetch('/api/drugs')
.then(response => response.json())
.then(json => setDrugs(json))
}, [drugs])
const [categories, setCategories] = React.useState([
{
id: 1,
name: "Miscellaneous analgesics"
},
{
id: 2,
name: "Benzodiazepines"
},
{
id: 3,
name: "Aminopenicillins"
},
{
id: 4,
name: "Miscellaneous antimalarials"
}
]);
const handleChange = (event) => {
console.log(event.target.value);
setPrescription({...prescription, drug: event.target.value});
}
<FormControl className={classes.formControl}>
<InputLabel htmlFor="grouped-select">Pharmaceutical Drugs</InputLabel>
<Select
id="grouped-select"
value={prescription.drug ? prescription.drug : ""}
onChange={handleChange}>
<MenuItem value="">
<em>None</em>
</MenuItem>
{categories.map(category =>
(<span>
<ListSubheader key={category.id}>{category.name}</ListSubheader>
{drugs.map(drug => drug.class===category.name ? <MenuItem key={drug._id} value={drug.name}>{drug.name}</MenuItem> : null)}
</span>)
)}
</Select>
<FormHelperText>Select a Pharmaceutical Drug to prescribe.</FormHelperText>
</FormControl>
This is the error I'm getting:
react_devtools_backend.js:2430 Material-UI: You have provided an
out-of-range value undefined for the select component. Consider
providing a value that matches one of the available options or ''. The
available values are 1, 2, 3
None of the values I select seem to work and show what I've selected as well. What am I doing wrong here?
I've adjusted the code a bit, if I add a dummy value to
<MenuItem value="">
<em>None</em>
</MenuItem>
Then I seem to be receiving a value from the console.log in handleChange, however, everything here returns me an undefined value. I've looked into React Developer Tools and every rendered MenuItem in the does have a value, an id and everything.
{categories.map(category =>
(<span>
<ListSubheader key={category.id}>{category.name}</ListSubheader>
{drugs.map(drug => drug.class===category.name ? <MenuItem key={drug._id} value={drug.value}>{drug.name}</MenuItem> : null)}
</span>)
)}
For anyone who still cares! The problem was with renderValue. I've made a renderValue function and passed it to select and return the value of the drug. Ensure to check material ui select docs if you guys get stuck. Nothing was wrong with my backend or front-end.
Solved!
Here is the working solution for it.
<Select
value={plant}
onChange={handleSelectChange}
renderValue={(selected) => {
if(selected)
return plant.modelName
}}
>
{plants.map((value) => (
<MenuItem value={value}>{value.modelName}</MenuItem>
))}
</Select>
You have to add 'renderValue' props to render the selected value.
I have a list of 3 status that should be shown as the default value but I need to remove one of those options from the dropdown. I was able to disable it using the isOptionDisabled prop but my goal is to remove.
Right now I have an object with the option
export const userStatus = [
{ label: 'Active', value: 'ACTIVE' },
{ label: 'Blocked', value: 'BLOCKED' },
{ label: 'Pending', value: 'ACTIVATION_PENDING', isDisabled: true },
];
I want to remove the pending from the dropdown but show as default value if it is the default value.
My select component looks like this
<Select
name={name}
fullWidth={fullWidth}
components={{ DropdownIndicator }}
isSearchable={false}
value={selectValue}
options={options}
classNamePrefix="styled-select"
variant={variant}
isDisabled={disabled}
hasError={hasError}
onChange={onSelectChange}
isOptionDisabled={isOptionDisabled}
/>
Can you filter the options before you send it as a prop to React-Select?