I am learning react and it's fun!
I am creating a sign up form in React using react-select.
I am mapping values from array:
const options = [ 'female', 'male', 'other']
<Select {...register("gender")}
label="Gender"
fullWidth
variant="outlined"
>
{options.map(value => (
<option key={value} value={value}>
{value}
</option>
))}
</Select>
But I get following warning:
Warning: Use the defaultValue or value props on instead of setting selected on .
Questions:
How do I use the defaultValue or value props on ?
I am setting label="Gender" but it is not visible, why?
const options = [
{ value: "female", label: "Female" },
{ value: "male", label: "Male" },
{ value: "other", label: "Other" }
];
export default function App() {
const [gender, setGender] = useState("");
const handleChange = (event) => {
setGender(event.target.value);
};
return (
<div className="App">
<Select
value={gender}
onChange={handleChange}
>
{options.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</div>
);
}
API reference: https://material-ui.com/api/select/
Working demo: https://codesandbox.io/s/pedantic-jones-dyfwd?file=/src/App.js:119-788
Related
I don't know how to pass values from dropdown on select to 4 inputs. My dropdown showing address as it should be but I struggle to pass each value to separate inputs.e.g address_1 should be in one input where is flat number, address_2 where is street etc.
const [select,setSelect]=useState()
<select onChange={(e) => setSelect(e.target.value)}>
<option>Select Address</option>
{getAddressData?.address? (
getAddressData?.address?.map((address: any, id) => (
<option>{`${address.Address_1},${address.Address_2}, ${address.Town}, ${address.County}`}</option>
<input>
type={'text'}
name={'flatNumber'}
placeholder="Flat Number"
value={select}
</input>
Right now I have whole line of address e.g (30 Ballot Street,Smethick,West Midlands) in the whole one input.
Here's the working code. It's live here: https://codesandbox.io/s/competent-firefly-0qdrij?file=/src/App.js
import React, { useState, useEffect } from "react";
function App() {
const [address, setAddress] = useState({
Address_1: "",
Address_2: "",
Town: "",
pafCounty: ""
});
let getAddressData = {};
getAddressData.address = [
{
Address_1: "Address_1",
Address_2: "Address_2",
Town: "Town",
pafCounty: "pafCounty"
},
{
Address_1: "Address_11",
Address_2: "Address_22",
Town: "Town2",
pafCounty: "pafCounty2"
}
];
function handleChange(e) {
setAddress({ ...address, [e.target.name]: e.target.value });
}
useEffect(() => {
console.log(address);
}, [address]);
return (
<>
<select
onChange={(e) => {
setAddress(getAddressData?.address[e.target.value]);
}}
>
<option selected disabled>
Select Address
</option>
{getAddressData?.address?.map((address, index) => (
<option
key={index}
value={index}
>{`${address.Address_1}, ${address.Address_2}, ${address.Town}, ${address.pafCounty}`}</option>
))}
</select>
{Object.keys(address).map((key, index) => (
<input
type="text"
name={key}
placeholder="Flat Number"
value={address[key]}
onChange={handleChange}
/>
))}
</>
);
}
export default App;
Instead of setSelect(e.target.value), set it to the original structured address object. You could have the value of the option be the index within the address list, for example, and then setSelect(getAddressData?.address[2]) or whatever.
I'm working on material ui react storybook . I have given customised select options but when i select options it is not selecting. Below is what i have tried if option 1 is selected it not taking any value. How do i select options ? I cannot use TextField , because i'm working on select component. I have to achieve this with the Mapping. Thanks. Below is My code.
export const SelectBasic= ({
props,
selectoptions,
}) => {
const theme = useTheme();
const [age, setAge] = React.useState('');
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.valueasstring);
};
return (
<div>
<FormControl fullWidth >
<InputLabel id="demo-simple-select-label">Age</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={age}
label="Age"
onChange={handleChange}
>
{selectoptions.map(item => {
return (
<MenuItem value={item.label}>{item.label}</MenuItem>
)
})}
</Select>
</FormControl>
</div >
);
}
stories.js
export const Selectdef = SelectBasic.bind({});
Selectdef .args = {
selectoptions: [{ "label": "Option 1" }, { "label": "Option 2" }, { "label": "Option 3" }],
};
const {
Box,
FormControl,
InputLabel,
MenuItem,
Select,
Typography
} = MaterialUI;
const OPTIONS = [{
value: 10,
label: 'ten'
},
{
value: 20,
label: 'twenty'
},
{
value: 30,
label: 'thirty'
}
];
const BasicSelect = ({options}) => {
const [age, setAge] = React.useState('');
const handleChange = (event) => {
setAge(event.target.value);
};
return (
<Box sx={{ minWidth: 120 }}>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">Age</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={age}
label="Age"
onChange={handleChange}
>
{options.map(item => <MenuItem value={item.value}>{item.label}</MenuItem>)}
</Select>
</FormControl>
<Typography>{`Currently selecting: ${age || 'undefined'}`}</Typography>
</Box>
);
}
ReactDOM.render( <BasicSelect options={OPTIONS} / > ,
document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/#mui/material#latest/umd/material-ui.production.min.js"></script>
In your onChange function where you set state.
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.valueasstring);
};
`event.target.value` should be sent to `setAge`.
There are some code style issues but this is what breaks the option selection.
Your map placement is incorrect and you are missing to set a value for the MenuItem
Try this:
return (
<div>
<FormControl fullWidth >
<InputLabel id="demo-simple-select-label">Age</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={age}
label="Age"
onChange={handleChange}
>
{selectoptions.map((item) => {
return(
<MenuItem value={item.label}>{item.label}</MenuItem>
)
})}
</Select>
</FormControl>
</div >
);
I created a Select using React that allows the user to select multiple options.
The problem is that the Select displays the ID of the selected item, instead of their name.
How can I change the code in a way that the Select display the names separated by commas (now shows the IDs separated by commas), while keeping the array of ids for later processing.
Any idea how to fix it? Here is the code to CodeSanbox
I have the following array in a Material UI Select:
const names = [
{ id: "1", value: "Oliver Hansen" },
{ id: "2", value: "Van Henry" },
{ id: "3", value: "Omar Alexander" }
];
This is the code that renders the Multiple Select:
<Select
labelId="demo-mutiple-checkbox-label"
id="demo-mutiple-checkbox"
multiple
value={personName}
name="first"
onChange={handleChange}
input={<OutlinedInput label="Tag" />}
renderValue={(selected) => selected.join(", ")}
>
{names.map((name) => (
<MenuItem key={name.id} value={name.id}>
<Checkbox checked={personName.indexOf(name.id) > -1} />
<ListItemText primary={name.value} />
</MenuItem>
))}
</Select>
I found one possible solution for your issue.
check if it works for you.
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import { Input, OutlinedInput } from "#material-ui/core";
import InputLabel from "#material-ui/core/InputLabel";
import FormControl from "#material-ui/core/FormControl";
import Select from "#material-ui/core/Select";
import MenuItem from "#material-ui/core/MenuItem";
import ListItemText from "#material-ui/core/ListItemText";
import Checkbox from "#material-ui/core/Checkbox";
const useStyles = makeStyles((theme) => ({
formControl: {
margin: theme.spacing(1),
minWidth: 300
},
selectEmpty: {
marginTop: theme.spacing(2)
}
}));
const names = [
{ id: "1", value: "Oliver Hansen" },
{ id: "2", value: "Van Henry" },
{ id: "3", value: "Van Henry" }
];
export default function NativeSelects() {
const classes = useStyles();
const [personName, setPersonName] = React.useState([]);
const handleChange = (event) => {
const {
target: { value }
} = event;
setPersonName(
// On autofill we get a the stringified value.
typeof value === "string" ? value.split(",") : value
);
};
return (
<div>
<FormControl className={classes.formControl}>
<InputLabel htmlFor="age-native-simple">
Names here to select from
</InputLabel>
<Select
labelId="demo-mutiple-checkbox-label"
id="demo-mutiple-checkbox"
multiple
value={personName}
name="first"
onChange={handleChange}
input={<OutlinedInput label="Tag" />}
renderValue={(selected) => selected.map(obj=> names[obj - 1].value).join(", ")}
>
{names.map((name) => (
<MenuItem key={name.id} value={name.id}>
<Checkbox checked={personName.indexOf(name.id) > -1} />
<ListItemText primary={name.value} />
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
Updated Code
just you can do this:
renderValue={
(selected) =>
names.filter( name => selected.includes(name.id) )
.map( record => record.name )
.join(", ")
}
To show the selected user's names, you can update the map part, where currently, you're using id.
You can update this to use the name.value to store/show the person's names.
{names.map((name) => (
<MenuItem key={name.value} value={name.value}>
<Checkbox checked={personName.indexOf(name.value) > -1} />
<ListItemText primary={name.value} />
</MenuItem>
))}
Updated Sandbox
the simple steps I did, just focus on the renderValue property, on the Select component:
renderValue={(selected) => names.find((val) => val.id === selected).value}
the logic I use, find the value in the 'names' array, where the id is the selected id, then take the 'value' value in the 'names' array, to display.
Update the Menu Items' value to be a object instead of an id.
<Select
labelId="demo-mutiple-checkbox-label"
id="demo-mutiple-checkbox"
multiple
value={personName}
name="first"
onChange={handleChange}
input={<OutlinedInput label="Tag" />}
renderValue={(selected) => selected.map((item) => item.value)?.join(",")}
>
{names.map((name) => (
<MenuItem key={name.id} value={name}>
<Checkbox
checked={personName.find((p) => p.id === name.id) !== undefined}
/>
<ListItemText primary={name.value} />
</MenuItem>
))}
</Select>
I am trying to create a multi-select form control, however, whenever I select something it does not get rendered. The function handleChange does get the event.target.value but it does not seem to add to the roleIds state. Furthermore, the console.log for the variable selected does not log anything to console.
Component Code:
const allRoleIds = [
"12345678",
"98765423",
"56465735683578",
];
const [roleIds, setRoleIds] = React.useState([]);
function handleChange(event) {
setRoleIds(event.target.value);
}
const [cassowaries, setCassowaries] = React.useState({
columns: [
{ title: "Cassowary Name", field: "name" },
{
title: "Cassowary Roles",
field: "roles",
render: (rowData) => {
return (
<li>
{rowData.roles.map((role) => (
<Chip label={role} className={classes.chip} />
))}
</li>
);
},
editComponent: (props) => (
<FormControl className={classes.formControl}>
<InputLabel>Roles</InputLabel>
<Select
multiple
value={roleIds}
onChange={handleChange}
input={<Input id="select-multiple-chip" />}
renderValue={(selected) => {
console.log(selected);
return (
<div className={classes.chips}>
{selected.map((value) => (
<Chip
key={value}
label={value}
className={classes.chip}
/>
))}
</div>
);
}}
// MenuProps={MenuProps}
>
{allRoleIds.map((id) => (
<MenuItem key={id} value={id}>
{id}
</MenuItem>
))}
</Select>
</FormControl>
),
},
{ title: "Penguin", field: "penguin" },
],
data: [{ name: "Mehmet", roles: roleIds, penguin: true }],
});
You are doing concat in your handleChange. Material ui already gives you the array of selected values to you. Sp fix your handleChange everything should be fine.
Like this
function handleChange(event) {
setRoleIds(event.target.value);
}
Working demo is here
EDIT:
Based on additional req (see comments):
If a custom multi select component needs to be used inside materail table editcomponent, then the state of select should not be managed outside but state & onChagne needs to managed inside editComponent using the prop it provides.
See working demo here
Code snippet - material ui table
...
columns: [
{ title: "Tag Name", field: "name" },
{
title: "Tag Roles",
field: "roles",
render: rowData => {
return (
<li>
{rowData.roles.map(role => (
<Chip label={role} className={classes.chip} />
))}
</li>
);
},
editComponent: props => {
console.log("props", props);
return (
<FormControl className={classes.formControl}>
<InputLabel>Roles</InputLabel>
<Select
multiple
value={props.value}
onChange={e => props.onChange(e.target.value)}
input={<Input id="select-multiple-chip" />}
renderValue={renderChip}
>
{allRoleIds.map(id => (
<MenuItem key={id} value={id}>
{id}
</MenuItem>
))}
</Select>
</FormControl>
);
}
},
{ title: "Penguin", field: "penguin" }
],
data: [{ name: "Mehmet", roles: [], penguin: true }]
...
const currencies = [
{
value: "USD",
label: "$",
name: "Dollar"
},
{
value: "EUR",
label: "€",
name: "Euro"
}
];
export default function MultilineTextFields() {
const [currency, setCurrency] = React.useState({
label: "€",
value: "EUR",
name: "Euro"
});
const handleChange = event => {
setCurrency(event.target.value);
};
return (
<form noValidate autoComplete="off">
{console.log(currency)}
<div>
<TextField
select
value={currency}
onChange={handleChange}
>
{currencies.map(option => (
<MenuItem key={option.value} value={option}>
{option.label}
</MenuItem>
))}
</TextField>
</div>
</form>
);
}
I can't set Object value in Select. If <MenuItem key={option.value} value={option.value}> not problem, But I need some value in Object for output. I must value={option} for print {currency.name} in some fields.
Provide a defaultValue prop for the wrapping "select" element/component, and specify a non-object value to the "option".
<TextField
id="standard-select-currency"
select
label="Select"
value={currency}
onChange={handleChange}
helperText="Please select your currency"
defaultValue="EUR"
>
{currencies.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>