Can't .map for a material RadioGroup - reactjs

I have:
const documentTypes = [
'General',
'Email',
'Fiction story',
'Blog post',
'Newsletter',
'Review',
'Website content'
]
and
<FormControl component="fieldset">
<FormLabel component="legend">Document Type</FormLabel>
<RadioGroup name="documentType" value={docType} onChange={handleChangeDoc}>
{documentTypes.map((documentType, idx) => {
<FormControlLabel value={documentType} control={<Radio />} label={documentType} key={idx} />
})}
<FormControlLabel value="other" control={<Radio />} label={<Input onFocus={() => setDocType('other')} />} />
</RadioGroup>
</FormControl>
but I don't see all of the options. Just the other. What am I doing wrong?
This is with material-ui for react.

I think you only need to return the FormControlLabel in the map.
Options 1) remove the {} around the FormControlLabel
<FormControl component="fieldset">
<FormLabel component="legend">Document Type</FormLabel>
<RadioGroup name="documentType" value={docType} onChange={handleChangeDoc}>
{documentTypes.map((documentType, idx) =>
<FormControlLabel value={documentType} control={<Radio />} label={documentType} key={idx} />
)}
<FormControlLabel value="other" control={<Radio />} label={<Input onFocus={() => setDocType('other')} />} />
</RadioGroup>
</FormControl>
Option 2) Just add return before FormControlLabel
<FormControl component="fieldset">
<FormLabel component="legend">Document Type</FormLabel>
<RadioGroup name="documentType" value={docType} onChange={handleChangeDoc}>
{documentTypes.map((documentType, idx) => {
return <FormControlLabel value={documentType} control={<Radio />} label={documentType} key={idx} />
})}
<FormControlLabel value="other" control={<Radio />} label={<Input onFocus={() => setDocType('other')} />} />
</RadioGroup>
</FormControl>

Related

Removing Items from an Array When Radio Button in Form is Selected/Form Submitted

I have developed a short questionnaire in React using Material-UI as shown below. I am pulling the questions from a json file I have that looks like the following:
[ {
"id": 1,
"question": "Which section 1 criterion are applicable?"
"criterion": ["1.1", "1.2", "1.3"]
"decision": "Yes"
},
{
"id": 2,
"question": "Which section 2 criterion are applicable?"
"criterion": ["2.1", "2.2", "2.3"]
"decision": "No"
},
...
]
At the start of the questionnaire, all criteria are added to applicableCriteria (shown below). Based on the user's responses, I am trying to remove criterion from applicableCriteria. For example, if the user responds 'Yes' to question 1, the list of criterion shown for the question with id=1 should be removed from applicableCriteria. I have experimented with some different things, but my novice JavaScript skills haven't gotten me far. Below is a working, error-free version of what I've been working with. Any tips on how I should go about this successfully?
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";
import { useForm } from "react-hook-form";
import Records from "./CriterionQuestions.json";
const QuestionnaireForm = () => {
const {
register,
handleSubmit,
watch,
formState: { errors },
} = useForm();
const onSubmit = (data) => console.log(data);
console.log(errors);
let applicableCriteria = [];
// Push all possible criteria to list
for (let q = 0; q < Records.length; q++) {
for (let c = 0; c < Records[q].criterion.length; c++) {
applicableCriteria.push(Records[q].criterion[c]);
}
}
return (
<div className="App__form">
<h1> Questionnaire </h1>
<h2>{applicableCriteria}</h2>
<form onSubmit={handleSubmit(onSubmit)}>
{/* Radio button */}
<FormControl error={Boolean(errors.question1)}>
<FormLabel component="legend">
{/* {" "}
Is the modification applicable to only fixed-wing and non-commercial
derivative aircraft?{" "} */}
{Records[0].question}
</FormLabel>
<RadioGroup row aria-label="question1" name="question1">
<FormControlLabel
value="yes"
control={
<Radio
{...register("question1", {
required: "Please select a response.",
})}
/>
}
label="Yes"
/>
<FormControlLabel
value="no"
control={
<Radio
{...register("question1", {
required: "Please select a response.",
})}
/>
}
label="No"
/>
</RadioGroup>
<FormHelperText style={{ color: "#d32f2f" }}>
{errors.question1?.message}
</FormHelperText>
</FormControl>
<FormControl error={Boolean(errors.question2)}>
<FormLabel component="legend">{Records[1].question}</FormLabel>
<RadioGroup row aria-label="question2" name="question2">
<FormControlLabel
value="yes"
control={
<Radio
{...register("question2", {
required: "Please select a response.",
})}
/>
}
label="Yes"
/>
<FormControlLabel
value="no"
control={
<Radio
{...register("question2", {
required: "Please select a response.",
})}
/>
}
label="No"
/>
</RadioGroup>
<FormHelperText style={{ color: "#d32f2f" }}>
{errors.question2?.message}
</FormHelperText>
</FormControl>
<div className="clearfix"></div>
<FormControl error={Boolean(errors.question8)}>
<FormLabel component="legend">{Records[7].question}</FormLabel>
<RadioGroup row aria-label="question8" name="question8">
<FormControlLabel
value="yes"
control={
<Radio
{...register("question8", {
required: "Please select a response.",
})}
/>
}
label="Yes"
/>
<FormControlLabel
value="no"
control={
<Radio
{...register("question8", {
required: "Please select a response.",
})}
/>
}
label="No"
/>
</RadioGroup>
<FormHelperText style={{ color: "#d32f2f" }}>
{errors.question8?.message}
</FormHelperText>
</FormControl>
<div className="clearfix"></div>
<FormControl error={Boolean(errors.question9)}>
<FormLabel component="legend">{Records[8].question}</FormLabel>
<RadioGroup row aria-label="question9" name="question9">
<FormControlLabel
value="yes"
control={
<Radio
{...register("question9", {
required: "Please select a response.",
})}
/>
}
label="Yes"
/>
<FormControlLabel
value="no"
control={
<Radio
{...register("question9", {
required: "Please select a response.",
})}
/>
}
label="No"
/>
</RadioGroup>
<FormHelperText style={{ color: "#d32f2f" }}>
{errors.question9?.message}
</FormHelperText>
</FormControl>
<div className="clearfix"></div>
<TextField
id="outlined-basic"
name="modName"
label="Modification Name"
variant="outlined"
fullWidth
{...register("modName", {
required: "Modification Name is required.",
})}
error={Boolean(errors.modName)}
helperText={errors.modName?.message}
/>
{/* Check box */}
<Box sx={{ paddingTop: 3 }} />
<div className="clearfix"></div>
<Button
variant="contained"
color="primary"
type="submit"
className="btns"
>
Submit Responses
</Button>
</form>
</div>
);
};
export default QuestionnaireForm;

ReactJS Material UI Reset Radio Buttons

I have Material UI radio buttons in my ReactJS form :
<FormControl className={ styles.rowControl }>
<FormLabel>Direction</FormLabel>
<RadioGroup name="direction" onChange={ this.setOption } ref={ this.directionGroupRef }>
<FormControlLabel
className={ styles.rowFirstLabel }
control={<Radio />}
label="North"
ref={ this.northRef }
value="North"
/>
<FormControlLabel
className={ styles.rowFirstLabel }
control={<Radio />}
label="South"
value="South"
/>
<FormControlLabel
className={ styles.rowFirstLabel }
control={<Radio />}
label="Flip-Flop"
value="Flip-Flop"
/>
</RadioGroup>
</FormControl>
How can I remove any checked statuses among these radio buttons when the form is submitted?

Radio Button passing null value on selecting female using react-hook-form

I want to get value on submit, but getting value which is first, its passing null value on selecting female , onChange its working fine
<form onSubmit={handleSubmit(onSubmit)}>
<FormControl>
<FormLabel id="demo-radio-buttons-group-label">Gender</FormLabel>
<RadioGroup
// onChange={(e)=> console.log(e.target.value)}
{...register("myrad")}
>
<FormControlLabel value="Male" control={<Radio />}label="Male" />
<FormControlLabel value="Female" control={<Radio />}label="Female" />
</RadioGroup>
</FormControl>
<button type="submit">submit</button>
</form>
Replace your form tag with this
<RadioGroup
// onChange={(e)=> console.log(e.target.value)}
name="use-radio-group"
defaultValue="Female"
>
<FormControlLabel
{...register("myrad")}
value="Male"
control={<Radio />}
label="Male"
/>
<FormControlLabel
{...register("myrad")}
value="Female"
control={<Radio />}
label="Female"
/>
</RadioGroup>

react-hook-form material-ui (FormControlLabel + Checkbox) using Controller

to use Material-ui in react-hook-form you should use <Controller and the method render instead of "as = {xy-control}" Also should not mix controller and inputRef = {register}.
A single control is also no problem.
But there is a compound control in Material-ui. "FormControlLabel + CheckBox" how do you integrate this control in the controller. All my attempts have failed.
This is how it works but I would like the FormControlLaben to be enclosed by the controller.
Does somebody has any idea?
<Controller
name="password"
control={control}
defaultValue={""}
render={(props) => <TextField {...props}
variant="outlined"
margin="normal"
required
fullWidth
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>}
/>
<FormControlLabel
control={
<Checkbox
inputRef={register}
name="remember"
/>
}
label="remember"
/>
{/*That works, but it requires an OnChange. Why can't the controller bind it?*/}
<FormControlLabel
control={
<Controller
name={"remember2"}
control={control}
render={(props) => (
<Checkbox
{...props}
onChange={(e) => props.onChange(e.target.checked)}
/>
)}
/>
}
label="remember"
/>
Here's how I did it
<FormControlLabel
control={
<Controller
control={control}
inputRef={register}
name='controlName'
render={({onChange, value}) => (
<Checkbox
onChange={e => onChange(e.target.checked)}
checked={value}
/>
)}
/>
}
label="This is a label"
/>
From v7, I used this :
<Controller
name='contactAutre'
control={control}
defaultValue={false}
render={({ field }) => (
<FormControlLabel
control={<Checkbox {...field} />}
label='Autre'
/>
)}
/>
this was enough for me w/ Mui 5 & RHF 7
const { watch, register } = useForm<{saveEmail: boolean}>({
defaultValues: { saveEmail: true },
});
...
<FormControlLabel
control={
<Checkbox {...register('saveEmail')} checked={watch('saveEmail')} />
}
label="save email"
/>
Credit to Leo Roese for his example for Textfield. However you can apply the same logic for Checkboxes but slightly tweak.
const { control, formState: { errors } } = useForm()
<Controller
name="privacyAccept"
control={control}
render={({ field }) => (
<>
<FormControlLabel
control={<Checkbox {...field} />}
label="I agree to the privacy policy"
/>
{errors.privacyAccept && (
<FormHelperText error>{errors.privacyAccept.message}</FormHelperText>
)}
</>
)}
/>
Another way to make things more controlled:
<FormControlLabel
label="label here"
control={
<Controller
name="isSeparatedDelivery"
control={control}
render={({ field: { onChange, value } }) => (
<Checkbox
checked={value}
onChange={(e) => onChange(e.target.checked)}
/>
)}
/>
}
/>
or
<Controller
control={control}
name="selected"
render={({ field: { onChange, value } }) => (
<FormControlLabel
control={
<Checkbox
label="Sélectionner la question"
checked={value}
onChange={onChange}
/>
}
label="Sélectionner la question"
/>
)}
/>

react-hook-form and MUI FormControl

So I am trying to register some radio buttons for my form, however it will not register.
<FormControl component="fieldset" inputRef={register({ required: true })}>
<FormLabel component="legend">Promoting</FormLabel>
<RadioGroup aria-label="promoting" name="promoting" value={promoting} onChange={handleChange} inputRef={register({ required: true })}>
<FormControlLabel value="business" control={<Radio />} label="Business" />
<FormControlLabel value="nonprofit" control={<Radio />} label="Non-Profit" />
<FormControlLabel value="event" control={<Radio />} label="Event" />
</RadioGroup>
</FormControl>
I am wondering what I am doing wrong
Full code:
export default function BuildAd() {
const [promoting, setValue] = React.useState('female');
const handleChange = (event) => {
setValue(event.target.value);
};
const { register, handleSubmit, errors } = useForm();
const onSubmit = data => console.log(data);
console.log(errors);
return (
<div style={{ padding: 16, margin: 'auto', maxWidth: 600 }}>
<CssBaseline />
<Typography variant="h5" align="center" component="h2" gutterBottom>
Create your campaign
</Typography>
<Paper style={{ padding: 16 }}>
<form onSubmit={handleSubmit(onSubmit)}>
<input type="text" placeholder="First name" name="First name" ref={register({required: true, maxLength: 80})} />
<input type="text" placeholder="Last name" name="Last name" ref={register({required: true, maxLength: 100})} />
<input type="text" placeholder="Email" name="Email" ref={register({required: true, pattern: /^\S+#\S+$/i})} />
<input type="tel" placeholder="Mobile number" name="Mobile number" ref={register({required: true, minLength: 6, maxLength: 12})} />
<select name="Title" ref={register({ required: true })}>
<option value="Mr">Mr</option>
<option value="Mrs">Mrs</option>
<option value="Miss">Miss</option>
<option value="Dr">Dr</option>
</select>
<input name="Developer" type="radio" value="Yes" ref={register({ required: true })}/>
<input name="Developer" type="radio" value="No" ref={register({ required: true })}/>
<Typography variant="h5">What are you Advertising</Typography>
<Box m={2}/>
<FormControl component="fieldset" inputRef={register({ required: true })}>
<FormLabel component="legend">Promoting</FormLabel>
<RadioGroup aria-label="promoting" name="promoting" value={promoting} onChange={handleChange} inputRef={register({ required: true })}>
<FormControlLabel value="business" control={<Radio inputRef={register({ required: true })} />} label="Business" />
<FormControlLabel value="nonprofit" control={<Radio inputRef={register({ required: true })} />} label="Non-Profit" />
<FormControlLabel value="event" control={<Radio inputRef={register({ required: true })} />} label="Event" />
</RadioGroup>
</FormControl>
<input type="submit" />
</form>
</Paper>
</div>
);
}
You can fallback on controllable components by using Controller if it doesn't work.
In your case, I suspect it's because the name props passed to your RadioGroup is not the same as the name attribute when passed into native inputs like input or select.
react-hook-form V7
const { handleSubmit, control } = useForm({
defaultValues: {
promoting2: '',
},
});
<FormControl component="fieldset">
<FormLabel component="legend">Promoting</FormLabel>
<Controller
rules={{ required: true }}
control={control}
name="promoting2"
render={({ field }) => (
<RadioGroup {...field}>
<FormControlLabel
value="business"
control={<Radio />}
label="Business"
/>
<FormControlLabel
value="nonprofit"
control={<Radio />}
label="Non-Profit"
/>
<FormControlLabel
value="event"
control={<Radio />}
label="Event"
/>
</RadioGroup>
)}
/>
</FormControl>
react-hook-form V6
const { register, handleSubmit, errors, control } = useForm({
promoting: '',
});
const onSubmit = (data) => alert(JSON.stringify(data, null, 2));
<form onSubmit={handleSubmit(onSubmit)}>
<FormControl component="fieldset">
<FormLabel component="legend">Promoting</FormLabel>
<Controller
rules={{ required: true }}
control={control}
name="promoting"
as={
<RadioGroup>
<FormControlLabel
value="business"
control={<Radio />}
label="Business"
/>
<FormControlLabel
value="nonprofit"
control={<Radio />}
label="Non-Profit"
/>
<FormControlLabel
value="event"
control={<Radio />}
label="Event"
/>
</RadioGroup>
}
/>
</FormControl>
<input type="submit" />
</form>
If you want to read the value when onChange fires, you cannot do that when passing the element to the as props:
<Controller
{...}
as={
<MyComponent
onChange={handleChange} // handleChange will never be called
/>
}
/>
The reason is because Controller will copy the element that you pass in and pass its own onChange props that will override yours. See here and here.
To fix that problem, you need to use another way to pass the element down by using render props to gain more control on how you should render your components.
<Controller
rules={{ required: true }}
control={control}
name="promoting2"
render={({ name, onBlur, onChange, value }) => (
<RadioGroup
value={value}
onBlur={onBlur}
onChange={(e) => {
onChange(e);
console.log(e.target.value); // will be called this time
}}
>
<FormControlLabel
value="business"
control={<Radio />}
label="Business"
/>
{...}
</RadioGroup>
)}
/>

Resources