How to display multiple varied states for multiple radio groups? - javascript

Currently using Semantic-UI-React in a form, and want to use multiple Radio sections in said form. In the SUIR example code, the selected radio button displays as a title via state, however I want to have multiple groupings of radio selection options that show the corresponding selected button value. How do I change the current writing for state to be able to reflect ONLY the selected radio value for the option grouping it is apart of?
I have tried adding and id attribute to the Radio element, and then changed the display title from {this.state.value} to {this.id.state.value}, but of course that does not work.
// Here is my state declaration:
state = {};
handleChange = (e, { value }) => this.setState({ value });
// The display title:
<Form.Field>
Category:
<b style={{ marginLeft: 20 }}>{this.state.value}</b>
</Form.Field>
//Grid row that displays the various radio options:
<Grid.Row id="Category" columns={4}>
<Grid.Column>
<Radio
label="Health & Wellness"
name="radioGroup"
value="Health & Wellness"
checked={this.state.value === "Health & Wellness"}
onChange={this.handleChange}
/>
</Grid.Column>
<Grid.Column>
<Radio
label="Finance"
name="radioGroup"
value="Finance"
checked={this.state.value === "Finance"}
onChange={this.handleChange}
/>
</Grid.Column>
<Grid.Column>
<Radio
label="Culture"
name="radioGroup"
value="Culture"
checked={this.state.value === "Culture"}
onChange={this.handleChange}
/>
</Grid.Column>
<Grid.Column>
<Radio
label="Other"
name="radioGroup"
value="Other"
checked={this.state.value === "Other"}
onChange={this.handleChange}
/>
</Grid.Column>
</Grid.Row>
This is copy and pasted again beneath for an additional radio grouping.
I expect the first to reference the relative selected value, and the second in the additional group to do the same, however when selecting any radio button in either group, the state reflects the selection value in both elements.

Use the name of each group as a property in state
state = {group1: null, group2: null};
handleChange = (e, {name, value }) => this.setState({[name]: value });
Two different group items:
/* group 1 */
<Grid.Column>
<Radio
label="Finance"
name="group1"
value="Finance"
checked={this.state.group1 === "Finance"}
onChange={this.handleChange}
/>
</Grid.Column>
/* group2 */
<Grid.Column>
<Radio
label="Culture"
name="group2"
value="Culture"
checked={this.state.group2 === "Culture"}
onChange={this.handleChange}
/>
</Grid.Column>

Related

Multiple values are getting selected in radio options

Created the multiple radio options, but it is allowing me to select more then one option.
{item.responseType === "radio" && (
<div className="form-control-wrap">
{item.options.split(",").map((list, index) => (
<Form.Check
key={index}
label={list}
name={list}
type="radio"
id={list}
/>
))}
</div>
)}
What changes need to be done to select only one option ?
If you want only one of them to be selectable. You must set the value of the name props to the same value for all of them. like this
name="radio-name" // use filed name
like this
{item.responseType === "radio" && (
<div className="form-control-wrap">
{item.options.split(",").map((list, index) => (
<Form.Check
key={index}
label={list}
name="radio-name"
type="radio"
id={list}
/>
))}
</div>
)}

Form not clickable until setInterval has been cleared in React useEffect

Link to sandbox replecating the behavior
sand box demo
I have a hook in a React component that I am using as a countdown for time to answer a question.
React.useEffect(() => {
const timer = setInterval(() => {
setTimeLeft((newTimeLeft) => newTimeLeft <= 0 ? 0 : newTimeLeft - 1);
}, 50);
return () => {
if(timeLeft <= 0){
clearInterval(timer);
}
};
}, []);
My form is very simple
<form>
<FormControl>
<RadioGroup aria-label="trivia" name="trivia" value={choice} onChange={handleUserChoice}>
{radioOptions}
</RadioGroup>
<Button variant="outlined" color="secondary" onClick={checkAnswer}>Check Choice</Button>
</FormControl>
</form>
radioOptions is a list of Radio Components making up the choices of answer.
radioOptions = currentQuestion.questionInfo.choices.map((option) => {
return (
<FormControlLabel key={option} value={option} control={<Radio />} label={option} />
)
})
The form is not interactive until after the countdown finishes and clearInterval is called.
I can't click to select any of the radio options in choices. The button works and triggers its function. But the radio options arent interactive until the interval is done.
So, the React.useEffect is just re-rendering the entire choices as the choices reside in the same class, so the choices are getting selected but as soon as the state changes (which is the counter running), the component re-renders the counter and the choices and it looks as if nothing is getting selected. Running the choices directly from the main component helped and it worked like you intended
<div className="App">
{timeLeft}
<form>
<p>Select a maintenance drone:</p>
{/* <Choices /> */}
<div>
<input type="radio" id="huey" name="drone" value="huey" />
<label htmlFor="huey">Huey</label>
</div>
<div>
<input type="radio" id="dewey" name="drone" value="dewey" />
<label htmlFor="dewey">Dewey</label>
</div>
<div>
<input type="radio" id="louie" name="drone" value="louie" />
<label htmlFor="louie">Louie</label>
</div>
<button disabled={timeLeft <= 0 ? true : false} onClick={checkChoice}>
Check Choice
</button>
</form>
</div>

Both Material-UI radio button are checked

I have a file which renders RadioGroup, FormControlLabel and FormControl. Below is the code for this
import React from 'react';
import PropTypes from 'prop-types';
import Radio from '#material-ui/core/Radio';
import RadioGroup from '#material-ui/core/RadioGroup';
import FormControl from '#material-ui/core/FormControl';
import FormLabel from '#material-ui/core/FormLabel';
import FormControlLabel from '#material-ui/core/FormControlLabel';
export const RenderRadioGroup = ({ label, children }) => {
return (
<FormControl>
<FormLabel
style={{
margin: '20px 0 20px 0',
color: '#000000',
fontSize: '20px',
fontWeight: 'bold',
}}
>
{label}
</FormLabel>
<RadioGroup row>{children}</RadioGroup>
</FormControl>
);
};
export const RenderRadioButtonWrapper = props => {
return <FormControlLabel control={<CustomRadioButton />} {...props} />;
};
export const CustomRadioButton = props => {
return <Radio {...props} />;
};
RenderRadioGroup.propTypes = {
children: PropTypes.node.isRequired,
label: PropTypes.string,
};
RenderRadioButtonWrapper.propTypes = {
label: PropTypes.string,
};
CustomRadioButton.propTypes = {
label: PropTypes.string,
};
In the main file, I am calling these components as follows
<form>
<Field
name="typeofintimation"
label="Type of intimation"
component={RenderRadioGroup}
>
<Field
label="Via Call"
name="viacall"
value="viacall"
component={RenderRadioButtonWrapper}
/>
<Field
label="Via Email"
name="viaemail"
value="viaemail"
component={RenderRadioButtonWrapper}
/>
</Field>
<Field component={renderTextFieldGroup} label="Caller Details">
<Field component={renderTextField} label="Caller Name" />
<Field component={renderTextField} label="Caller Email" />
<Field component={renderTextField} label="Caller Contact" />
</Field>
</form>
I am getting the radio fields but both are checked. I cannot select or deselect the radio buttons.
What am I missing here? Is there some props which I need to pass in either the component or the main file?
I am also using redux-form here so I need some assitance in that.
You need to explicitly supply a name in the props so that the system knows that the two radio buttons belong to the same group. The documentation for the API in its list of props says:
name string The name used to reference the value of the control. If
you don't provide this prop, it falls back to a randomly generated
name.
See https://material-ui.com/api/radio-group/ for the full list.
Radio buttons are grouped by name - so if you click one of the buttons in a group all the others are cleared. You have the two radio buttons but they have different names so the system thinks they are in different groups and so both can be checked.
If you try replacing:
<Field
label="Via Call"
name="viacall"
value="viacall"
component={RenderRadioButtonWrapper}
/>
<Field
label="Via Email"
name="viaemail"
value="viaemail"
component={RenderRadioButtonWrapper}
/>
with
<Field
label="Via Call"
name="viamethod"
value="viacall"
component={RenderRadioButtonWrapper}
/>
<Field
label="Via Email"
name="viamethod"
value="viaemail"
component={RenderRadioButtonWrapper}
/>
you can only select one in 'naked' HTML. However, where you are creating the radio buttons using the API you need to explicitly set name: and make it the same name for both e.g. name: 'viamethod' otherwise you will get random names and the two radio buttons won't be in the same group.
start with radioValue's state as "".
<RadioGroup row className={classes.FormGroup}>
<FormControlLabel
classes={{ label: classes.label }}
control={
<Radio
name="Yes"
checked={this.state.radioValue[key]}
onClick={(e) => {this.handleRowClick(e, row, index)}}
value="Y"
/>
}
label="Yes"
labelPlacement="end"
/>
<FormControlLabel
classes={{ label: classes.label }}
control={
<Radio
name="No"
checked={this.state.radioValue[key]}
onClick={(e) => {this.handleRowClick(e, row)}}
color="secondary"
value="N"
/>
}
label="No"
labelPlacement="end"
/>
</RadioGroup>

react radio button doesn't work on the first click

I have a radio button using pure css, but it doesn't work on first click, it only work on the second click onward, not sure it has to do with my react prop or not:
const Radio = ({ id, name, value, checked, children }) => (
<div className="radioBtn">
<input type="radio" value={value} id={id} name={name} checked={checked} />
<label className={"radio"} htmlFor={id}>
<span className={"big"}>
<span className={"small"} />
</span>
<span>{children}</span>
</label>
</div>
);
https://codesandbox.io/s/react-sass-34b8w
Use defaultChecked instead of checked={checked}.

Change color of Material UI Indeterminate Checkbox

I'm having a hard time applying a color to the indeterminate state of my checkboxes. When fully selected, the checkbox properly displays as the secondary color. Any suggestions on what I'm doing wrong to target the indeterminate state and change its color?
const styles = {
root: {
'&$indeterminate': {
color: 'red',
},
},
indeterminate: {},
};
...
<ListItem
dense
button
key={this.props.key}
className={this.props.className}
disabled={this.props.disabled}
onClick={this.props.onClick}
>
<Checkbox
indeterminate={this.props.indeterminate}
classes={{
root: classes.root,
indeterminate: classes.indeterminate,
}}
disableRipple
tabIndex={-1}
disabled={this.props.disabled}
checked={this.props.checked}
/>
<ListItemText inset primary={this.props.text} />
{ hasChildren ? <ExpansionIcon onClick={this.onExpansionItemClick} /> : null }
</ListItem>
I did it this way based on the documentation here: https://material-ui.com/customization/overrides/#overriding-with-classes
Thanks for your help!
I've found the proper way to implement this. Instead of selecting the root and changing the color, you tell the Checkbox what icon to use and apply a class to the icon.
<Checkbox
indeterminate={this.props.indeterminate}
indeterminateIcon={<IndeterminateCheckBoxIcon className={classes.root} />}
disableRipple
tabIndex={-1}
disabled={this.props.disabled}
checked={this.props.checked}
/>

Categories

Resources