React radio button button checked attribute not working - javascript

I have a react component that resembles a radio button input section. I have the checked attribute on each radio input set to a true or false expression, but it does not end up working when I run it.
Any idea on why the item isn't being lit up when a new item is selected? When I log the expression (console.log), I get the correct result.
My code looks like this:
class MyClass extends Component {
constructor(props) {
super(props);
this.state = {
currentItem: 1,
}
}
updateCurrentItem = (event) => {
let key = `${event.currentTarget.id}`;
this.currentItem = key;
console.log(!(1 % this.currentItem));
}
isOn(id) {
return (!(id % this.currentItem));
}
render() {
return (
<div className="iconList">
<input type="radio" id="one" name="picker" value="one" checked={this.isOn(1)}/>
<label for="one"><button id={1} onClick={this.updateCurrentItem}>One</button></label>
<input type="radio" id="two" name="picker" value="two" checked={this.isOn(2)}/>
<label for="two"><button id={2} onClick={this.updateCurrentItem}>Two</button></label>
<input type="radio" id="three" name="picker" value="three" checked={this.isOn(3)}/>
<label for="three"><button id={3} onClick={this.updateCurrentItem}><Three</button></label>
<input type="radio" id="four" name="picker" value="four" checked={this.isOn(4)}/>
<label for="four"><button id={4} onClick={this.updateCurrentItem}>Four</button></label>
</div>
);
}
}
export default MyClass;
Any help is much appreciated. Thanks!

You should use this.state and this.setState. Here's a working example:
https://codesandbox.io/s/sleepy-dew-thglz?file=/src/App.js

Related

Can't select radio buttons when checked status has some logic

I have a couple of checkboxes that are refusing to be checked.
export default function App() {
let model = {};
return (
<div className="App">
<h1>Hello React Radio Buttons</h1>
<p>
Sure the model object is empty, so initially the radio will be
unchecked, but why can't I manually check it?
</p>
<div>
<input type="radio" id="opt1" checked={model.selection === "opt1"} />
<label htmlFor="opt1">Option 1</label>
</div>
<div>
<input type="radio" id="opt2" checked={model.selection === "opt2"} />
<label htmlFor="opt2">Option 2</label>
</div>
</div>
);
}
Here is a sandbox link.
The above is a simple test scenario, but I am glad I was able to replicate the problem.
The real scenario is I am trying to maintain the status of what radio button was checked when I come back to the page from an error state (i.e. form was submitted, there were errors, I want to come back to the page and maintain the selections).
Because your model does't have selection key. It's better to use useStates hook same as bellow:
export default function App() {
let model = {};
const [checked1, setChecked1] = useState(model.selection === "opt1");
const [checked2, setChecked2] = useState(model.selection === "opt2");
return (
<div className="App">
<h1>Hello React Radio Buttons</h1>
<p>
Sure the model object is empty, so initially the radio will be
unchecked, but why can't I manually check it?
</p>
<div>
<input
type="radio"
id="opt1"
onChange={() => setChecked1(!checked1)}
checked={checked1}
/>
<label htmlFor="opt1">Option 1</label>
</div>
<div>
<input
type="radio"
id="opt2"
onChange={() => setChecked2(!checked2)}
checked={checked2}
/>
<label htmlFor="opt2">Option 2</label>
</div>
</div>
);
}

How to disable a checkbox after executing onChange method?

I want to be able to disable a checkbox once I check on the checkbox and execute the onChange method.
I was able to find a way to do this, but once multiple items are checked only the recently checked checkbox is disabled.
The disable method is inside a component class before the render method
Disable = id => {
document.getElementById(id).disabled = true;
//another method to execute onchange
};
<span>
<input
type="checkbox"
className="form-check-input"
onChange={this.Disable}
value=""
/>
</span>;
The checkbox is inside the render method.
One the user checks the checkbox the checkbox needs to check and disable it self
Some notice points:
use camelCase for function name
use props value to make the checkbox fully controlled
use props disabled to disable input element
set the related state inside the handler function
no need for document.getElementById in your current situation
handler event is not id, if you just need id, pass it as a param this.handler(id)
Demo:
const App = () => {
const [checked, setChecked] = React.useState(false);
const [status, setStatus] = React.useState(true);
const onChangeHandler = () => {
setChecked(!checked);
setStatus(false);
};
return (
<div className="App">
<input
type="checkbox"
value={checked}
disabled={!status}
onChange={onChangeHandler}
/>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
you should have to attach id on element .
let Disable=(id)=>{
if(id){
document.getElementById(id).disabled = true
}
}
<span>
<input type="checkbox" className="form-check-input" onChange="Disable(this.id)" id="one" value=""/>
<input type="checkbox" className="form-check-input" onChange="Disable(this.id)" id="two" value=""/>
<input type="checkbox" className="form-check-input" onChange="Disable(this.id)" id="three" value=""/>
</span>
passing the event in an anonymous arrow function and accepting it as an argument in the eventHandler(component method) and using the event.target there is the appropriate way of doing this in such situations that you need to access the caller.
class Stack extends Component {
Disable = event => {
event.target.disabled = true;
//another method to execute onChange
};
render() {
return (
<span>
<input
type="checkbox"
className="form-check-input"
onChange={event => this.Disable(event)}
value=""
/>
<input
type="checkbox"
className="form-check-input"
onChange={event => this.Disable(event)}
value=""
/>
<input
type="checkbox"
className="form-check-input"
onChange={event => this.Disable(event)}
value=""
/>
</span>
);
}
}

How to reference currect element inside its defaultChecked - React

I have a dynamic array
a[1,3]
I have 3 checkboxes which have name and value and I want to default check them based on the dynamic array a. I want to pass inside defaultCheck each current child's value (by reference and not manually by the actual number(1,2,3)).Is that possible?
Something like defaultChecked={giveCheck(self.value} and be executed in the beginning so the checkboxes get their default check status
<input type="checkbox" name="a" value="1" defaultChecked={giveCheck(self.value}/>
<input type="checkbox" name="a" value="2" defaultChecked={giveCheck(self.value}/>
<input type="checkbox" name="a" value="3" defaultChecked={giveCheck(self.value}/>
giveCheck(value) {
if(a.indexOf(value)>=0){
return true;
}
return false;
}
Old answer
Yes, that's definitely possible. In my example below I store the array in the state and for each of your inputs you check in that value exists in the array. You can use indexOf() if you want, but I prefer includes() as it is supported on all major browsers.
Also, you might want to change your name attributes to be unique.
class MyApp extends React.Component {
constructor() {
super();
this.state = {
a: [1,3]
};
}
render() {
return(
<div>
<input type="checkbox" name="a" value="1" defaultChecked={this.state.a.includes(1)} />
<input type="checkbox" name="b" value="2" defaultChecked={this.state.a.includes(2)} />
<input type="checkbox" name="c" value="3" defaultChecked={this.state.a.includes(3)} />
</div>
);
}
}
ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
If you have more than 3 elements (say 50) and code readability is a concern, you can generate the inputs in a loop:
class MyApp extends React.Component {
constructor() {
super();
this.state = {
a: [1,3]
};
}
render() {
return(
<div>
{[...Array(50)].map(
(v, i) => {
return <input type="checkbox" name={"a"+i} value={i+1} defaultChecked={this.state.a.includes(i+1)} />
})
}
</div>
);
}
}
ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
New answer
The short answer is: no, you cannot read the property of value before the component has been rendered. Basically what you are asking is for the code to read what you wrote earlier in the code. Unlike an event that triggers at runtime, this would have to happen on execution.
You could obviously just write the number twice:
<input type="checkbox" name="a" value="3" defaultChecked={giveCheck(3)}/>
but if you don't want this, create a function that returns an input element. This also eliminates the need for a "checker" function - just do it all in one function. This way, you input the value once, but can return code that uses that parameter in both places:
class MyApp extends React.Component {
constructor() {
super();
this.state = {
a: [1,3]
};
}
renderInput(value) {
return <input type="checkbox" name="a" value={value} defaultChecked={this.state.a.includes(value)} />
}
render() {
return(
<div>
{this.renderInput(1)}
{this.renderInput(2)}
{this.renderInput(3)}
</div>
);
}
}
ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

React controlled radio buttons not being checked

I have a child component that receives props from a parent. In the child component it renders a couple radio buttons like this:
<div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={this._handleInputChange}
value="1"
checked={this.props.value === "1"}
/>
True
</label>
</div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={this._handleInputChange}
value="0"
checked={this.props.value === "0"}
/>
False
</label>
</div>
</div>
handleInputChange just calls a parent method like so:
_handleInputChange(e) {
this.props.handleChange(e);
}
that will set the state of the parent component to the value selected in the radio buttons (i.e. "1" or "0"). The issue im having is that the checked conditionals return the correct props, but they function strangely. It almost seems like when the radio input receives a new prop value, it doesn't re render with checked. When the component first renders, the props.value is an empty string. When a user selects a radio button it changes the state of the parent component with _handleInputChange and then sends that value back down for the conditionals.
Thanks to some of the help here and on IRC I figured out it was a preventDefault in my event handler. After removing that it worked perfectly!
You must use state for checked property if you want react re-render radio button.
Example:
<div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={this._handleInputChange}
value="1"
checked={this.state.radioButton1}
/>
True
</label>
</div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={this._handleInputChange}
value="0"
checked={this.state.radioButton2}
/>
False
</label>
</div>
</div>
You also set value for state like this (alternatively, you can initialize it with getInitialState):
this.setState({
radioButton1 : props.value ==="1",
radioButton2 :props.value ==="0"
});
And in _handleInputChange function you're able to know that radio button is checked or unchecked by checking it's state.
_handleInputChange(e) {
var isChecked = e.target.value ==="1" ? this.state.radioButton1 : this.state.radioButton2;
this.props.handleChange(e);
}
use bind method to bind context this._handleInputChange.bind(this) in the constructor,or use (e)=>this._handleInputChange(e) on click ,when the event handler executed normally has no context.
or declared as this below,it can bind this automatically:
class ButtonGroup extends Component{
....
_handleInputChange= (e)=>{
...
}
sample below:
class ButtonGroup extends Component {
render() {
return (
<div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={(e) => this._handleInputChange(e)}
value="1"
checked={this.props.value === "1"}
/>
True
</label>
</div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={(e) => this._handleInputChange(e)}
value="0"
checked={this.props.value === "0"}
/>
False
</label>
</div>
</div>
);
}
_handleInputChange(e) {
this.props.handleChange(e);
}
}
class Form extends Component {
constructor(props) {
super(props);
this.state = {value: '1'};
}
render() {
var value = this.state.value;
return <ButtonGroup value={value} handleChange={(e) => this.valueChanged(e)}/>
}
valueChanged(e) {
this.setState({value: e.target.value});
}
}
ReactDOM.render(
<Form />,
document.getElementById('container')
);

In React, how to use one method to toggle states for multiple checkboxes values

_toggleValue: function(state) {
//?? how to do it
//this.setState(???);
},
render() {
<div>
<form>
<input type="checkbox" onChange={this._toggleValue.bind(null, this.state.a)} />
<input type="checkbox" onChange={this._toggleValue.bind(null, this.state.b)} />
<input type="checkbox" onChange={this._toggleValue.bind(null, this.state.c)} />
</form>
</div>
}
There are quite lot checkboxes in the form, currently, what I am doing is to define one method for each checkbox. How can I define one method which can be used by all the checkboxes.
Many thanks in advance
You could use the LinkedStateMixin.
Your checkboxes would look something like this:
<input type='checkbox' checkedLink={this.linkState('a')}/>
<input type='checkbox' checkedLink={this.linkState('b')}/>
<input type='checkbox' checkedLink={this.linkState('c')}/>
This will automatically keep the values of the checkboxes a, b and c up to date with the state variables.
You can use an id on your checkboxes and retrieve it from event.target.id that is passed to onChange handler as below:
_toggleValue: function(event) {
var state = this.state[event.target.id];
},
render: function() {
return (
<div>
<form>
<input type="checkbox" id={1} onChange={this._toggleValue}/>
<input type="checkbox" id={2} onChange={this._toggleValue}/>
<input type="checkbox" id={3} onChange={this._toggleValue}/>
</form>
</div>
)
}
I did it this way:
toggleCheckbox(name, event) {
let change = !this.state[name];
this.setState({name: change});
}
<input type="checkbox" name="active" defaultChecked={this.state.active} onChange={this.toggleCheckbox.bind(this, 'active')} />
<input type="checkbox" name="shared" defaultChecked={this.state.shared} onChange={this.toggleCheckbox.bind(this, 'shared')} />
Note the "defaultChecked" and that I'm not using the preventDefault() statement.

Categories

Resources