I'm using a RadioGroup component to display a dynamic list of Radio options using FormControlLabel. The dynamic radio options are successfully getting displayed and I'm able to retrieve the selected radio option using onChange in RadioGroup. However, when I check a radio option, that particular option does not appear "checked".
Here's the code I'm using:
export default class Book extends Component {
state = {
slot: null,
};
...
onChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
};
...
<FormControl component="fieldset" className={classes.formControl}>
<FormLabel component="legend">Select availability slot</FormLabel>
<RadioGroup
aria-label="Slot"
name="slot"
className={classes.group}
value={this.state.slot}
onChange={this.onChange}
>
{this.props.experience.availability !== null ? (
this.props.experience.availability.map(single => (
<FormControlLabel
key={single.id}
value={single.id}
control={<Radio color="primary" />}
label={single.title}
/>
))
) : ""}
// Some manual options in addition to the above dynamic list
<FormControlLabel
value="female"
control={<Radio color="primary" />}
label="Female"
/>
<FormControlLabel
value="male"
control={<Radio color="primary" />}
label="Male"
/>
</RadioGroup>
</FormControl>
...
}
this.props.experience.availability is an array of objects that I'm getting from a call I'm making to the backend. The call is being made in componentDidMount(). I use Redux, which makes the result available as a prop.
Now, if I manually add a few FormControlLabel components in the same RadioGroup, I can see that it's checked after selecting that option.
I've taken two screenshots - this is when the manual FormControlLabel is selected: https://ibb.co/pL5Fy6L and this is when one of my dynamic option is selected: https://ibb.co/Jq7mLN4
You can see that in the second one, the "Female" option gets unchecked but the option that I selected (20-06-2019) does not appear to be checked.
Can you please help me fix this?
Thanks in advance!
For anybody who might be facing the same issue, here's what I was doing wrong.
The problem was that I was passing an integer value to the value prop instead of a string like: value={single.id} so I added toString() to convert it to string like this: value={single.id.toString()} and it's working fine now.
Related
I am creating a React form using Material UI components. I have an empty array questionAns that I am using to keep track of the responses. I want to add an element, say yes to the array when the Yes radio button is selected on the form. Here is a subset of the form I am building:
import * as React from "react";
import TextField from "#mui/material/TextField";
import {
Button,
Radio,
RadioGroup,
FormControlLabel,
FormControl,
FormLabel,
FormHelperText,
FormGroup,
Checkbox,
Grid,
Box,
} from "#mui/material";
...
<FormControl error={Boolean(errors.question1)}>
<FormLabel component="legend">
{Records[0].question}
</FormLabel>
<RadioGroup row aria-label="question1" name="question1">
<FormControlLabel
value="Yes"
control={
<Radio
{...register("awQuestion1", {
required: "Please select a response.",
})}
/>
}
label="Yes"
/>
<FormControlLabel
value="No"
control={
<Radio
{...register("awQuestion1", {
required: "Please select a response.",
})}
/>
}
label="No"
/>
</RadioGroup>
<FormHelperText style={{ color: "#d32f2f" }}>
{errors.question1?.message}
</FormHelperText>
</FormControl>
How can I incorporate some sort of write function to accommodate my desired functionality? I'm not very familiar with JavaScript and React, but I would like to incorporate this hopefully simple feature.
I have a series of questions in the same structure as above.
Thank you.
You need to use a hook - useState - to keep track of the "Yes" answers, for example at the top of your component declare an answersArray state and its setter function:
const [answersArray, setAnswersArray] = useState([]);
Then on the radio buttons add an onChange prop
onChange={(e)=>{
if(e.checked) setAnswersArray((prevState)=> [...prevState, "Yes"]) //"No" on the no button
}
This is just the jist check out the docs for a better tutorial
https://beta.reactjs.org/reference/react/useState
I am trying to add a button to the Material UI autocomplete throgh the renderOption prop and added a button at each row which was supposed to display a PopOver component, but clicking on the button automatically closes the autocomplete search results
How can I prevent the autocomplete search results from closing on click
Here is a sandbox with my code: https://codesandbox.io/s/compassionate-rgb-z88y10
I have already checked this other similar issue, but in my case I am trying to set thr renderOption prop and not the PaperComponent
But unfortunatelly in my case it wasn´t enough to just set the function to run on the onMouseDown event handler
You can create a controlled Autocomplete by using the open prop on the component. The onClose gives you various reasons why the Popover wants to close, you can find them all in the MUI docs.
We check if the reason is selectOption if it is we do nothing and return out. If it is not we set isOpen to false to close the Popover
const [isOpen, setIsOpen] = useState(false);
return (
<Autocomplete
renderOption={(props, label) => (
<PopOver
{...props}
id={props.id}
label={label.label}
message={label.label}
/>
)}
id="combo-box-demo"
open={isOpen}
onOpen={() => setIsOpen(true)}
onClose={(e, reason) => {
if (reason === "selectOption") return;
setIsOpen(false);
}}
options={top100Films}
sx={{ width: 300 }}
renderInput={(params) => <TextField {...params} label="Movie" />}
/>
);
I have a MUI autocomplete with a a list of items and an edit icon next to each one which rerenders the option as a textfield to allow changing the name of the option but when I click inside textfield the dropdonwn closes.
I tried using autoFocus on the textfield but that makes the dropdown close as soon as I click the edit icon
It seems that whenever the autocomplete input looses focus it closes, is there any way to prevent this?
const [isEdit, SetIsEdit] = useState(false);
const [name, SetName] = useState('Blue');
<Autocomplete
options={data}
value={val}
onChange={(e, val)=> {handleChange(e, val)}}
filterSelectedOptions
// --------------- OPTION RENDER ---------------
renderOption={(props, option) => {
isEdit ?
<Box {...props}>
<Textfield value={name} onChange={()=>{setName(e.target.value)}}/>
<DoneIcon onClick={()=>{setIsEdit(false)}}/>
</Box>
:
<Box {...props}>
<Typography>{option.label}</Typography>
<EditIcon onClick={()=>{setIsEdit(true)}}/>
</Box>
}}
/>
);
}
You could be looking for the Autocomplete disableCloseOnSelect boolean prop. The MUI docs say this about the prop:
If true, the popup won't close when a value is selected.
The popup is the box that appears containing the autocomplete drop-down list of options.
I have edit mode in my material table. Each row contains two dropdowns. First dropdown has static list of options on selection in the on change handler ajax call is made to fetch list of options for second dropdown, the response with list of options is saved in the state, which causes component re-render and and disables edit mode- which I dont want. I want to keep edit moda until I click save button. I wonder if there is some method/option that I can access via tableRef that could help me?
title: 'Category',
field: 'category',
editComponent: ({ value, onChange }) => (
<Select
fullWidth
value={value ?? ''}
onChange={(event) => {
onChange(event.target.value);
dispatch(actions.getSubcategoriesList(event.target.value)).then((data) => {
setSubcategories(data);
});
}}
style={{ backgroundColor: '#f06565' }}
>
{actualsCategories.map((cat) => (
<MenuItem key={cat.id} value={cat.id}>
{cat.name}
</MenuItem>
))}
</Select>
),
I'm trying to make a form with two fields using react hook form where the required value of the text field depends on the value of the select drop down.
Here is my code:
const { handleSubmit, control, errors } = useForm();
const [isPickupPoint, togglePickupPoint] = useState(false);
const handleDestinationTypeChange: EventFunction = ([selected]) => {
togglePickupPoint(selected.value === "PICKUP_POINT");
return selected;
};
<Grid item xs={6}>
<InputLabel>Destination type</InputLabel>
<Controller
as={Select}
name="destinationType"
control={control}
options={[
{ label: "Pickup point", value: "PICKUP_POINT" },
{ label: "Shop", value: "SHOP" },
]}
rules={{ required: true }}
onChange={handleDestinationTypeChange}
/>
{errors.destinationType && (
<ErrorLabel>This field is required</ErrorLabel>
)}
</Grid>
<Grid item xs={6}>
<Controller
as={
<TextField
label="Pickup Point ID"
fullWidth={true}
disabled={!isPickupPoint}
/>
}
control={control}
name="pickupPointId"
rules={{ required: isPickupPoint }}
/>
{errors.pickupPointId && (
<ErrorLabel>This field is required</ErrorLabel>
)}
</Grid>
<Grid item xs={12}>
<Button
onClick={onSubmit}
variant={"contained"}
color={"primary"}
type="submit"
>
Save
</Button>
</Grid>
The isPickupPoint flag changes properly because the disabled prop of the textfield works fine. Only when the PICKUP_POINT option is selected the text field is active. But the required prop is not working, it is always false. When I try submitting the form when its empty the destinationType error label appears, but when I try to submit the form with the PICKUP_POINT option and empty pickupPointId field it passes with no errors.
How can I make this dynamic required prop work?
Based on the code here, it looks like isPickUpPoint is working as expected since it works for disable. Since you are using the same property for required, it should flow through. I would suspect that the bug may lie in your Controller component. I would take a look there and make sure that the property is what you expected to be.
Also for disabled the condition is !isPickUpPoint, so it will trigger when it's false.
For required the condition is isPickUpPoint so it will trigger when it's true.
That's also a bit of a disconnect since it looks like it's the same input.