React Checkbox not sending onChange - checkbox

TLDR: Use defaultChecked instead of checked, working jsbin.
Trying to setup a simple checkbox that will cross out its label text when it is checked. For some reason handleChange is not getting fired when I use the component. Can anyone explain what I'm doing wrong?
var CrossoutCheckbox = React.createClass({
getInitialState: function () {
return {
complete: (!!this.props.complete) || false
};
},
handleChange: function(){
console.log('handleChange', this.refs.complete.checked); // Never gets logged
this.setState({
complete: this.refs.complete.checked
});
},
render: function(){
var labelStyle={
'text-decoration': this.state.complete?'line-through':''
};
return (
<span>
<label style={labelStyle}>
<input
type="checkbox"
checked={this.state.complete}
ref="complete"
onChange={this.handleChange}
/>
{this.props.text}
</label>
</span>
);
}
});
Usage:
React.renderComponent(CrossoutCheckbox({text: "Text Text", complete: false}), mountNode);
Solution:
Using checked doesn't let the underlying value change (apparently) and thus doesn't call the onChange handler. Switching to defaultChecked seems to fix this:
var CrossoutCheckbox = React.createClass({
getInitialState: function () {
return {
complete: (!!this.props.complete) || false
};
},
handleChange: function(){
this.setState({
complete: !this.state.complete
});
},
render: function(){
var labelStyle={
'text-decoration': this.state.complete?'line-through':''
};
return (
<span>
<label style={labelStyle}>
<input
type="checkbox"
defaultChecked={this.state.complete}
ref="complete"
onChange={this.handleChange}
/>
{this.props.text}
</label>
</span>
);
}
});

To get the checked state of your checkbox the path would be:
this.refs.complete.state.checked
The alternative is to get it from the event passed into the handleChange method:
event.target.checked

It's better not to use refs in such cases. Use:
<input
type="checkbox"
checked={this.state.active}
onClick={this.handleClick}
/>
There are some options:
checked vs defaultChecked
The former would respond to both state changes and clicks.
The latter would ignore state changes.
onClick vs onChange
The former would always trigger on clicks.
The latter would not trigger on clicks if checked attribute is present on input element.

If you have a handleChange function that looks like this:
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value,
});
}
You can create a custom onChange function so that it acts like an text input would:
<input
type="checkbox"
name="check"
checked={this.state.check}
onChange={(e) => {
this.handleChange({
target: {
name: e.target.name,
value: e.target.checked,
},
});
}}
/>

In the scenario you would NOT like to use the onChange handler on the input DOM, you can use the onClick property as an alternative. The defaultChecked, the condition may leave a fixed state for v16 IINM.
class CrossOutCheckbox extends Component {
constructor(init){
super(init);
this.handleChange = this.handleChange.bind(this);
}
handleChange({target}){
if (target.checked){
target.removeAttribute('checked');
target.parentNode.style.textDecoration = "";
} else {
target.setAttribute('checked', true);
target.parentNode.style.textDecoration = "line-through";
}
}
render(){
return (
<span>
<label style={{textDecoration: this.props.complete?"line-through":""}}>
<input type="checkbox"
onClick={this.handleChange}
defaultChecked={this.props.complete}
/>
</label>
{this.props.text}
</span>
)
}
}
I hope this helps someone in the future.

In case someone is looking for a universal event handler the following code can be used more or less (assuming that name property is set for every input):
this.handleInputChange = (e) => {
item[e.target.name] = e.target.type === "checkbox" ? e.target.checked : e.target.value;
}

onChange will not call handleChange on mobile when using defaultChecked. As an alternative you can can use onClick and onTouchEnd.
<input onClick={this.handleChange} onTouchEnd={this.handleChange} type="checkbox" defaultChecked={!!this.state.complete} />;

In material ui, state of checkbox can be fetched as
this.refs.complete.state.switched

Related

Change the input type on-focus in JSX doesn't work

I have a text field which has the placeholder "Dates From". what I wanna do is to change It's input box type to a date type on the focus event. But
but the below mentioned solution doesn't work with JSX.
<input placeholder="Date" type="text" onFocus="(this.type='date')" id="date">
How to make this thing work on ReactJs or How to achieve the same goal?
Using an anonymous function should work, with e.target:
<input placeholder="Date" type="text" onFocus={(e) => e.target.type = 'date'} id="date" />
You can see it in action here.
Try this code
handleFocus(event) {
event.target.type = 'date';
}
render() {
return (
<label>
Name:
<input type="text" placeholder="please Enter date" onFocus={this.handleFocus.bind()} />
</label>
);
}
Perhaps you could take a state based approach to this, where you would update the state of the component to track the type of the input field when onFocus occours by doing something like this:
onFocus={ () => this.setState({ typeOfFocused : 'date' }) }
Doing this would trigger a re-render which in turn would cause the input element's type to switch to date via the following:
render() {
// Extract typeOfFocused from state
const { typeOfFocused } = this.state
// Render input type with typeOfFocused if present, or as text by default
return (<input placeholder="Date"
type={ typeOfFocused || 'text' }
onFocus={ () => this.setState({ typeOfFocused : 'date' }) }
onBlur={ () => this.setState({ typeOfFocused : '' }) }
id="date">)
}
Here's a working sample

How to fetch input from text box and print in React?

I am new to React trying to write a very simple project that fetches input of both text boxes and when button is clicked, the 'data' in text boxes is printed on paragraph.
How do I fetch text's in input text boxes when button is clicked?
class Input extends Component {
state = {
tagged: false,
message: '',
}
handleClick(e) {
this.setState({tagged: true});
e.preventDefault();
console.log('The link was clicked.');
}
render() {
return (
<div id="id" style={divStyle}>
<p> hello </p>
<input
style = {textStyle}
placeholder="user#email.com"
type="text">
</input>
<input
style = {textStyle}
placeholder="tag"
type="text">
</input>
<button
onClick={(e) => this.handleClick(e)}
style={buttonStyle}>
{this.state.tagged ? 'Tagged' : 'Tag ' }
</button>
<p>
{this.state.tagged ? 'Clicked' : 'Still' }
</p>
</div>
)
}
}
You can add onChange event handler in each input.
class Input extends Component {
state = {
tagged: false,
message: '',
input1: '',
input2: '',
}
handleClick(e) {
// access input values in the state
console.log(this.state) // {tagged: true, input1: 'text', input2: 'text2'}
this.setState({tagged: true});
e.preventDefault();
console.log('The link was clicked.');
}
handleInputChange = (e, name) => {
this.setState({
[name]: e.target.value
})
}
render() {
return (
<div id="id" style={divStyle}>
<p> hello </p>
<input
style = {textStyle}
placeholder="user#email.com"
type="text"
onChange={(e) => this.handleInputChange(e, 'input1')}
>
</input>
<input
style = {textStyle}
placeholder="tag"
type="text"
onChange={(e) => this.handleInputChange(e, 'input2')}
>
</input>
<button
onClick={(e) => this.handleClick(e)}
style={buttonStyle}>
{this.state.tagged ? 'Tagged' : 'Tag ' }
</button>
<p>
{this.state.tagged ? 'Clicked' : 'Still' }
</p>
</div>
)
}
}
There are two different ways of working with react inputs - you can either make them controlled or uncontrolled. When you say fetch text from inputs, this is called uncontrolled components and means that form data is handled by the DOM itself and not by react.
This is achieved by using ref and literally getting a reference to your input and fetching its value when you need it. you can read more about this approach in react docs.
According to react docs, it is recommended using controlled components
In most cases, we recommend using controlled
components to implement forms. In a controlled
component, form data is handled by a React component.
This means that you don’t use references to the inputs and instead handle changes of your inputs with an event handler and update state with the new values that the user has entered into the input fields. According to react docs here is how react handles form with controlled components:
the React component that
renders a form also controls what happens in that form on subsequent
user input. An input form element whose value is controlled by React in this way is called a “controlled component”.
In your case you can do this if you choose controlled inputs:
class ControlledInput extends React.Component {
constructor(props) {
super(props);
this.state = {
tagged: false,
firstInput: '',
secondInput: ''
}
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({ [event.target.name]: event.target.value });
}
handleClick(e) {
this.setState({ tagged: true });
e.preventDefault();
console.log('The link was clicked.');
}
render() {
const { firstInput, secondInput, tagged } = this.state;
return (
<div id="id">
{tagged && <p>{firstInput} {secondInput}</p> }
<input
value={firstInput}
name="firstInput"
onChange={this.handleChange}
type="text" />
<input
value={secondInput}
name="secondInput"
onChange={this.handleChange}
type="text" />
<button onClick={(e) => this.handleClick(e)}>
{tagged ? 'Tagged' : 'Tag '}
</button>
</div>
)
}
}
Here you put the inputs' values on state and update state when the user writes something in your inputs. If you however want to use uncontrolled components you can do it this way:
class UncontrolledInput extends React.Component {
state = {
tagged: false,
message: '',
}
handleClick(e) {
e.preventDefault();
const messageFromInputs = `${this.firstInput.value} ${this.secondInput.value}`;
this.setState({ tagged: true, message: messageFromInputs });
}
render() {
return (
<div id="id">
<p>{this.state.message}</p>
<input ref={(input) => this.firstInput = input} type="text" />
<input ref={(input) => this.secondInput = input} type="text" />
<button onClick={(e) => this.handleClick(e)}>
{this.state.tagged ? 'Tagged' : 'Tag '}
</button>
<p>
{this.state.tagged ? 'Clicked' : 'Still'}
</p>
</div>
)
}
}
Here you will actually fetch values from your inputs when the button is clicked.
I made a working example with both ways on codesandbox.

React. Can I get rid of ref in favor of onChange?

According to React spec:
https://reactjs.org/docs/refs-and-the-dom.html
"There are a few good use cases for refs:
Managing focus, text selection, or media playback.
Triggering imperative animations.
Integrating with third-party DOM libraries.
Avoid using refs for anything that can be done declaratively."
That's why I'm not so sure for now, whether I used ref properly or not in this case:
export let FormInput = createReactClass({
handleInput(e){
e.preventDefault();
const product = this.name.value;
const red = this.red.checked;
this.props.addProduct(product,red);
this.inputForm.reset();
},
render(){
return(
<form className="prod_input" ref={x => this.inputForm = x} onSubmit={this.handleInput}>
<input type="text" ref={x => this.name = x} placeholder="Product name"/>
<input type="checkbox" ref={x => this.red = x} value="true"/>
<input type="submit" hidden/>
</form>
)
}
})
If not, how could it be rearranged in order to replace ref to onChange={}?
You can avoid using refs by making your input fields controlled. Here is an example:
export let FormInput = createReactClass({
constructor(props){
super(props);
this.state = {
name: '',
};
}
handleNameChange(updatedName){
this.setState({ name: updatedName });
}
handleInput(e){
e.preventDefault();
const product = this.state.name;
// ...
this.props.addProduct(product);
this.inputForm.reset();
},
render(){
return (
<form className="prod_input" ref={x => this.inputForm = x} onSubmit={this.handleInput}>
<input type="text" value={this.state.name} placeholder="Product name" onChange={e => this.handleNameChange(e.target.value)} />
// ...
</form>
);
}
})
The idea is to keep the value of your fields in your local state. Then you can set the value of each of your fields to the value currently stored in your state, and attach an onChange handler that updates this value every the user types something. When you submit your form, all your values are available directly in your component's state.

React Modifying Textarea Values

I am working on a project which is basically notepad. I am having problems though updating the <textarea>'s value when an ajax call is made. I tried setting the textarea's value property but then no changes to its value can be made. How can I make it so on a state change the textarea's value changes and can be edited.
The code I have is as follows.
In the parent class
<Editor name={this.state.fileData} />
In the Editor class
var Editor = React.createClass({
render: function() {
return (
<form id="noter-save-form" method="POST">
<textarea id="noter-text-area" name="textarea" value={this.props.name}></textarea>
<input type="submit" value="Save" />
</form>
);
}
});
I can't use defaultValue because the value of the textarea is not known on page load and when I try and put the data between the textareas nothing happens. I would like it to take the state value whenever the state changes but have it editable in between.
Thanks
Edit
I managed to get it working using jQuery but would like to do it in React instead, I called this before render:
$('#noter-text-area').val(this.props.name);
I think you want something along the line of:
Parent:
<Editor name={this.state.fileData} />
Editor:
var Editor = React.createClass({
displayName: 'Editor',
propTypes: {
name: React.PropTypes.string.isRequired
},
getInitialState: function() {
return {
value: this.props.name
};
},
handleChange: function(event) {
this.setState({value: event.target.value});
},
render: function() {
return (
<form id="noter-save-form" method="POST">
<textarea id="noter-text-area" name="textarea" value={this.state.value} onChange={this.handleChange} />
<input type="submit" value="Save" />
</form>
);
}
});
This is basically a direct copy of the example provided on https://facebook.github.io/react/docs/forms.html
Update for React 16.8:
import React, { useState } from 'react';
const Editor = (props) => {
const [value, setValue] = useState(props.name);
const handleChange = (event) => {
setValue(event.target.value);
};
return (
<form id="noter-save-form" method="POST">
<textarea id="noter-text-area" name="textarea" value={value} onChange={handleChange} />
<input type="submit" value="Save" />
</form>
);
}
Editor.propTypes = {
name: PropTypes.string.isRequired
};
As a newbie in React world, I came across a similar issues where I could not edit the textarea and struggled with binding. It's worth knowing about controlled and uncontrolled elements when it comes to react.
The value of the following uncontrolled textarea cannot be changed because of value
<textarea type="text" value="some value"
onChange={(event) => this.handleOnChange(event)}></textarea>
The value of the following uncontrolled textarea can be changed because of use of defaultValue or no value attribute
<textarea type="text" defaultValue="sample"
onChange={(event) => this.handleOnChange(event)}></textarea>
<textarea type="text"
onChange={(event) => this.handleOnChange(event)}></textarea>
The value of the following controlled textarea can be changed because of how
value is mapped to a state as well as the onChange event listener
<textarea value={this.state.textareaValue}
onChange={(event) => this.handleOnChange(event)}></textarea>
Here is my solution using different syntax. I prefer the auto-bind than manual binding however, if I were to not use {(event) => this.onXXXX(event)} then that would cause the content of textarea to be not editable OR the event.preventDefault() does not work as expected. Still a lot to learn I suppose.
class Editor extends React.Component {
constructor(props) {
super(props)
this.state = {
textareaValue: ''
}
}
handleOnChange(event) {
this.setState({
textareaValue: event.target.value
})
}
handleOnSubmit(event) {
event.preventDefault();
this.setState({
textareaValue: this.state.textareaValue + ' [Saved on ' + (new Date()).toLocaleString() + ']'
})
}
render() {
return <div>
<form onSubmit={(event) => this.handleOnSubmit(event)}>
<textarea rows={10} cols={30} value={this.state.textareaValue}
onChange={(event) => this.handleOnChange(event)}></textarea>
<br/>
<input type="submit" value="Save"/>
</form>
</div>
}
}
ReactDOM.render(<Editor />, document.getElementById("content"));
The versions of libraries are
"babel-cli": "6.24.1",
"babel-preset-react": "6.24.1"
"React & ReactDOM v15.5.4"

How to set default Checked in checkbox ReactJS?

I'm having trouble to update the checkbox state after it's assigned with default value checked="checked" in React.
var rCheck = React.createElement('input',
{
type: 'checkbox',
checked: 'checked',
value: true
}, 'Check here');
After assigning checked="checked", I cannot interact the checkbox state by clicking to uncheck/check.
To interact with the box you need to update the state for the checkbox once you change it. And to have a default setting you can use defaultChecked.
An example:
<input type="checkbox" defaultChecked={this.state.chkbox} onChange={this.handleChangeChk} />
There are a few ways to accomplish this, here's a few:
Written using State Hooks:
function Checkbox() {
const [checked, setChecked] = React.useState(true);
return (
<label>
<input type="checkbox"
defaultChecked={checked}
onChange={() => setChecked(!checked)}
/>
Check Me!
</label>
);
}
ReactDOM.render(
<Checkbox />,
document.getElementById('checkbox'),
);
Here is a live demo on JSBin.
Written using Components:
class Checkbox extends React.Component {
constructor(props) {
super(props);
this.state = {
isChecked: true,
};
}
toggleChange = () => {
this.setState({
isChecked: !this.state.isChecked,
});
}
render() {
return (
<label>
<input type="checkbox"
defaultChecked={this.state.isChecked}
onChange={this.toggleChange}
/>
Check Me!
</label>
);
}
}
ReactDOM.render(
<Checkbox />,
document.getElementById('checkbox'),
);
Here is a live demo on JSBin.
If the checkbox is created only with React.createElement then the property
defaultChecked is used.
React.createElement('input',{type: 'checkbox', defaultChecked: false});
Credit to #nash_ag
In the React rendering lifecycle, the value attribute on form elements
will override the value in the DOM. With an uncontrolled component,
you often want React to specify the initial value, but leave
subsequent updates uncontrolled. To handle this case, you can specify
a defaultValue or defaultChecked attribute instead of value.
<input
type="checkbox"
defaultChecked={true}
/>
Or
React.createElement('input',{type: 'checkbox', defaultChecked: true});
Please checkout more details regarding defaultChecked for checkbox below:
https://reactjs.org/docs/uncontrolled-components.html#default-values
in addition to the correct answer you can just do :P
<input name="remember" type="checkbox" defaultChecked/>
import React, { useState } from 'react'
const [rememberUser, setRememberUser] = useState(true) //use false for unchecked initially
<input
type="checkbox"
checked={rememberUser}
onChange={() => {
setRememberUser(!rememberUser)
}}
/>
Value would be whether true or false defaultChecked={true}
<input type="checkbox"
defaultChecked={true}
onChange={() => setChecked(!checked)}
/>
It`s working
<input type="checkbox" value={props.key} defaultChecked={props.checked} ref={props.key} onChange={this.checkboxHandler} />
And function init it
{this.viewCheckbox({ key: 'yourKey', text: 'yourText', checked: this.state.yourKey })}
You may pass "true" or "" to the checked property of input checkbox. The empty quotes ("") will be understood as false and the item will be unchecked.
let checked = variable === value ? "true" : "";
<input
className="form-check-input"
type="checkbox"
value={variable}
id={variable}
name={variable}
checked={checked}
/>
<label className="form-check-label">{variable}</label>
I tried to accomplish this using Class component:
you can view the message for the same
.....
class Checkbox extends React.Component{
constructor(props){
super(props)
this.state={
checked:true
}
this.handleCheck=this.handleCheck.bind(this)
}
handleCheck(){
this.setState({
checked:!this.state.checked
})
}
render(){
var msg=" "
if(this.state.checked){
msg="checked!"
}else{
msg="not checked!"
}
return(
<div>
<input type="checkbox"
onChange={this.handleCheck}
defaultChecked={this.state.checked}
/>
<p>this box is {msg}</p>
</div>
)
}
}
Here's a code I did some time ago, it might be useful.
you have to play with this line => this.state = { checked: false, checked2: true};
class Componente extends React.Component {
constructor(props) {
super(props);
this.state = { checked: false, checked2: true};
this.handleChange = this.handleChange.bind(this);
this.handleChange2 = this.handleChange2.bind(this);
}
handleChange() {
this.setState({
checked: !this.state.checked
})
}
handleChange2() {
this.setState({
checked2: !this.state.checked2
})
}
render() {
const togglecheck1 = this.state.checked ? 'hidden-check1' : '';
const togglecheck2 = this.state.checked2 ? 'hidden-check2' : '';
return <div>
<div>
<label>Check 1</label>
<input type="checkbox" id="chk1"className="chk11" checked={ this.state.checked } onChange={ this.handleChange } />
<label>Check 2</label>
<input type="checkbox" id="chk2" className="chk22" checked={ this.state.checked2 } onChange={ this.handleChange2 } />
</div>
<div className={ togglecheck1 }>show hide div with check 1</div>
<div className={ togglecheck2 }>show hide div with check 2</div>
</div>;
}
}
ReactDOM.render(
<Componente />,
document.getElementById('container')
);
CSS
.hidden-check1 {
display: none;
}
.hidden-check2 {
visibility: hidden;
}
HTML
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
here's the codepen => http://codepen.io/parlop/pen/EKmaWM
In my case I felt that "defaultChecked" was not working properly with states/conditions. So I used "checked" with "onChange" for toggling the state.
Eg.
checked={this.state.enabled} onChange={this.setState({enabled : !this.state.enabled})}
If someone wants to handle dynamic data with multiple rows, this is for handing dynamic data.
You can check if the rowId is equal to 0.
If it is equal to 0, then you can set the state of the boolean value as true.
interface MyCellRendererState {
value: boolean;
}
constructor(props) {
super(props);
this.state = {
value: props.value ? props.value : false
};
this.handleCheckboxChange = this.handleCheckboxChange.bind(this);
}
handleCheckboxChange() {
this.setState({ value: !this.state.value });
};
render() {
const { value } = this.state;
const rowId = this.props.rowIndex
if (rowId === 0) {
this.state = {
value : true }
}
return (
<div onChange={this.handleCheckboxChange}>
<input
type="radio"
checked={this.state.value}
name="print"
/>
</div>
)
}
Don't make it too hard. First, understand a simple example given below. It will be clear to you. In this case, just after pressing the checkbox, we will grab the value from the state(initially it's false), change it to other value(initially it's true) & set the state accordingly. If the checkbox is pressed for the second time, it will do the same process again. Grabbing the value (now it's true), change it(to false) & then set the state accordingly(now it's false again. The code is shared below.
Part 1
state = {
verified: false
} // The verified state is now false
Part 2
verifiedChange = e => {
// e.preventDefault(); It's not needed
const { verified } = e.target;
this.setState({
verified: !this.state.verified // It will make the default state value(false) at Part 1 to true
});
};
Part 3
<form>
<input
type="checkbox"
name="verified"
id="verified"
onChange={this.verifiedChange} // Triggers the function in the Part 2
value={this.state.verified}
/>
<label for="verified">
<small>Verified</small>
</label>
</form>
<div className="display__lbl_input">
<input
type="checkbox"
onChange={this.handleChangeFilGasoil}
value="Filter Gasoil"
name="Filter Gasoil"
id=""
/>
<label htmlFor="">Filter Gasoil</label>
</div>
handleChangeFilGasoil = (e) => {
if(e.target.checked){
this.setState({
checkedBoxFG:e.target.value
})
console.log(this.state.checkedBoxFG)
}
else{
this.setState({
checkedBoxFG : ''
})
console.log(this.state.checkedBoxFG)
}
};
You can use a state var "enableSwitch" and a function "handleSwitch" to handle your default checked Switch:
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="switchId" checked={this.state.enableSwitch} onClick={this.handleSwitch}/>
<label class="custom-control-label" for="switchId">switch text</label>
</div>
Here's the function which inverts the variable if the user clicks on the switch:
handleSwitch = (e) => {
this.setState({ enableSwitch: !this.state.enableSwitch });
}
I know it's a late reply to an old question, but this short solution may help other users.
<div className="form-group">
<div className="checkbox">
<label><input type="checkbox" value="" onChange={this.handleInputChange.bind(this)} />Flagged</label>
<br />
<label><input type="checkbox" value="" />Un Flagged</label>
</div>
</div
handleInputChange(event){
console.log("event",event.target.checked) }
the Above handle give you the value of true or false upon checked or unChecked
I set the state as any[] type. and in the constructor set the state to null.
onServiceChange = (e) => {
const {value} = e.target;
const index = this.state.services.indexOf(value);
const services = this.state.services.filter(item => item !== value);
this.setState(prevState => ({
services: index === -1 ? prevState.services.push(value) && prevState.services : this.state.services.filter(item => item !== value)
}))
}
In the input element
this.onServiceChange(e)}/>
this.onServiceChange(e)}/>
this.onServiceChange(e)}/>
this.onServiceChange(e)}/>
I figured it out after some time. Thought it might help y'all :)

Resources