React checkboxes "Cannot read property" error - javascript

i am trying checkboxes (component) in react and trying to get all the variables checked. I wrote the code as:
import React, { Component } from 'react'
import {
Card,
Container,
CardBody,
Form,
FormGroup,
Label,
Input,
Button,
} from "reactstrap";
export default class Chk extends React.Component {
states={
Colornames:{
ship:false,
cabin:false,
grade:false,
rate:false,
marketing:false,
image:false
}
}
chkClick = (e) => {
var {name, checked} = e.target;
var name = e.target.name;
var checked = e.target.checked;
console.log("xxxxx", e.Colornames)
this.setState((e) => {
var SelectedSport = e.Colornames;
return SelectedSport[name]=checked;
});
};
render() {
var displaySports = Object.keys(this.states.Colornames);
console.log("aaaaaa", displaySports)
return (
<div>
<center>
<input type="checkbox" name="ship" onChange={this.chkClick}/> Ship
<input type="checkbox" name="cabin" onChange={this.chkClick}/> Cabin
<input type="checkbox" name="grade" onChange={this.chkClick}/> Grade
<input type="checkbox" name="rate" onChange={this.chkClick}/> Rate
<input type="checkbox" name="marketing" onChange={this.chkClick}/> Marketing
<input type="checkbox" name="image" onChange={this.chkClick}/> Image
</center>
</div>
)
}
}
This is giving error:
TypeError: Cannot read property 'Colornames' of null
i feel its all fine with the code.
Finally i need all the checkboxes value (checked: true/false) so that i can do a search from the data as per the checkboxes checked
BTW i am using a mac machine with chrome browser.

Just went through the problem statement again, and found out that the state initialisation wasn't correct. While using the React Class Components, the state should be initialised inside the constructor. I have tried to make the function chkClick a little simpler and everything is working as per exepctation.
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
colornames: {
ship: false,
cabin: false,
grade: false,
rate: false,
marketing: false,
image: false
}
}
}
chkClick = (e) => {
var { name, checked } = e.target;
console.log(name, checked);
this.setState((prevState) => {
return {
colornames: {
...prevState.colornames,
[name]: checked
}
}
});
}
render() {
return (
<div>
<center>
<input type="checkbox" name="ship" onChange={this.chkClick} /> Ship
<input type="checkbox" name="cabin" onChange={this.chkClick} /> Cabin
<input type="checkbox" name="grade" onChange={this.chkClick} /> Grade
<input type="checkbox" name="rate" onChange={this.chkClick} /> Rate
<input type="checkbox" name="marketing" onChange={this.chkClick} /> Marketing
<input type="checkbox" name="image" onChange={this.chkClick} /> Image
</center>
</div>
)
}
}

Related

Can't uncheck checkbox using react

This checkbox is permanently checked, I want the pre selected checkbox to change the boolean state. I'm currently using this handleChange method to deal with text inputs. Do I have to create another method to deal with the checkbox or can I add to the existing method?
state = {
billingEmail:'',
billingAddressSame: true,
}
handleChange = input => e => {
this.setState({[input]: e.target.value})
}
<input
className="col-sm-12"
type="email"
placeholder="Email"
onChange={handleChange('billingEmail')}
defaultValue={values.billingEmail}
/>
<label className="col-sm-12" style={{paddingLeft: "0"}}>
<input
type="checkbox"
checked={values.billingAddressSame}
onChange={handleChange('billingAddressSame')}
/>
Same as company address
</label>
Change your handleChange function to
handleChange = input => e => {
this.setState({[input]: !this.state[input]})
}
You can control your checkbox and input by a single method.
See
Constructor and handle change function-
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
And in your render function -
render() {
return (
<form>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
</form>
);
}
See this for more info
try this and let me know, its working fine for me
import React, { Component, Fragment } from 'react';
class SignUp extends Component{
state = {
billingEmail:'',
billingAddressSame: true,
}
render(){
return(<Fragment>
<input className="input" type="email" className="col-sm-12" placeholder="Email" value={this.state.billingEmail} onChange={e => this.setState({billingEmail: e.target.value})}/>
<label className="col-sm-12" style={{paddingLeft: "0"}}>
<input type="checkbox" value="CheckBox1" checked={this.state.billingAddressSame} onChange={e => this.setState({ billingAddressSame: !this.state.billingAddressSame })} />
Same as company address
</label>
</Fragment>)
}
}
export default SignUp;

Radio button cannot return different state

I am fairly new to developing web app using React.js and Firebase so pardon me if my question doesn't seems relevant.
I have this simple web app where user can choose an option from multiple choices using radio button. When the user finished answering the questions, they will submit their answers and the answers will be submitted to the Firebase.
Now I'm stuck at writing the chosen value to the Firebase. There are 2 issues for me:
1) The radio button can only be clicked once. Meaning that users cannot answer the second question without the first answer being deselected.
2) When I clicked on submit, all the other option returns the same values as the chosen option.
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import logo from './logo.svg';
import './App.css';
import firebase from './firebase.js';
class App extends Component {
constructor(){
super();
this.state = {
owl: '',
house: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
render(){
return(
<div>
<ol type="1">
<form onSubmit={this.handleSubmit}>
<li><p>What is the name of Harry Potter's owl?</p></li>
<ol type="a">
<div className="radio">
<label>
<li><input type="radio" name="owl" value="hedwig" checked={this.state.owl === "hedwig"} onChange={this.handleChange}/>
Hedwig<br></br></li>
<li><input type="radio" name="owl" value="ron" checked={this.state.owl === "ron"} onChange={this.handleChange}/>
Ron <br></br></li>
<li><input type="radio" name="owl" value="brian" checked={this.state.owl === "brian"} onChange={this.handleChange}/>
Brian</li>
<br></br>
<br></br>
</label>
</div>
</ol>
<li><p>What is the name of Cho Chang's house?</p></li>
<ol type="a">
<div className="radio">
<label>
<li><input type="radio" name="house" value="gryffindor" checked={this.state.house === "gryffindor"} onChange={this.handleChange}/>
Gryffindor<br></br></li>
<li><input type="radio" name="house" value="slytherin" checked={this.state.house === "slytherin"} onChange={this.handleChange}/>
Slytherin <br></br></li>
<li><input type="radio" name="house" value="ravenclaw" checked={this.state.house === "ravenclaw"} onChange={this.handleChange}/>
Ravenclaw</li>
<br></br>
<br></br>
</label>
</div>
</ol>
<button>Submit!</button>
</form>
</ol>
</div>
)
}
handleChange = (e) =>{
this.setState({
owl: e.target.value,
house: e.target.value
});
}
handleSubmit = (e) =>{
e.preventDefault();
const itemsRef = firebase.database().ref('answers');
const item = {
owl: this.state.owl,
house: this.state.house
}
itemsRef.push(item);
this.setState({
owl: '',
house: ''
});
}
}
export default App;
I found the answer already, after 12 hours of searching and staring at the code.
I just needed to set a unique name for the onChange method. Here's what I have done.
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import logo from './logo.svg';
import './App.css';
import firebase from './firebase.js';
class App extends Component {
constructor(){
super();
this.state = {
owl: '',
house: ''
};
//owlChange and houseChange are now exclusively for owl and house values respectively
this.owlChange = this.owlChange.bind(this);
this.houseChange = this.houseChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
render(){
return(
<div>
<ol type="1">
<form onSubmit={this.handleSubmit}>
<li><p>What is the name of Harry Potter's owl?</p></li>
<ol type="a">
<div className="radio">
<label>
<li><input type="radio" name="owl" value="hedwig" checked={this.state.owl === "hedwig"} onChange={this.owlChange}/>
Hedwig<br></br></li>
<li><input type="radio" name="owl" value="ron" checked={this.state.owl === "ron"} onChange={this.owlChange}/>
Ron <br></br></li>
<li><input type="radio" name="owl" value="brian" checked={this.state.owl === "brian"} onChange={this.owlChange}/>
Brian</li>
<br></br>
<br></br>
</label>
</div>
</ol>
<li><p>What is the name of Cho Chang's house?</p></li>
<ol type="a">
<div className="radio">
<label>
<li><input type="radio" name="house" value="gryffindor" checked={this.state.house === "gryffindor"} onChange={this.houseChange}/>
Gryffindor<br></br></li>
<li><input type="radio" name="house" value="slytherin" checked={this.state.house === "slytherin"} onChange={this.houseChange}/>
Slytherin <br></br></li>
<li><input type="radio" name="house" value="ravenclaw" checked={this.state.house === "ravenclaw"} onChange={this.houseChange}/>
Ravenclaw</li>
<br></br>
<br></br>
</label>
</div>
</ol>
<button>Submit!</button>
</form>
</ol>
</div>
)
}
owlChange = (e) =>{
this.setState({
owl: e.target.value
});
}
houseChange = (e) =>{
this.setState({
house: e.target.value
});
}
handleSubmit = (e) =>{
e.preventDefault();
const itemsRef = firebase.database().ref('answers');
const item = {
owl: this.state.owl,
house: this.state.house
}
itemsRef.push(item);
this.setState({
owl: '',
house: ''
});
}
}
export default App;

How can I append objects to the body of a component in React?

I am trying to set up some functionality on this React component so that a user can add and remove empty radio button options to a page that a user can type text into. The only issue that I am having is that I am relatively new to React and am not 100% how to do this.
import React, { Component } from 'react';
class TextRadio extends Component {
constructor() {
super();
state = {
textValue: ""
}
};
handleInputChange = event => {
const value = event.target.value;
const name = event.target.name;
this.setState({
[name]: value
});
}
addBox = () => {
}
removeBox = () => {
}
render() {
return(
<div>
<div className="form-check">
<input className="form-check-input" type="radio" id="" name="" value="" />
<label className="form-check-label" for="">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
<button type="button" className="btn btn-danger" onClick={this.removeBox}>
Remove Option
</button>
</div>
);
}
}
export default TextRadio;
The result that I am expecting to happen is to have it so the component can add and remove radio button options from the page depending on the button that the user presses
i was completed just your addBox and RemoveBox functions, i hope that's help you
import React, { Component } from "react";
class TextRadio extends Component {
constructor() {
super();
this.state = {
radioButtons: []
};
}
handleInputChange = event => {
const value = event.target.value;
const name = event.target.name;
};
addBox = () => {
this.setState(prevstate => {
let radioButtons = prevstate.radioButtons;
if (radioButtons.length === 0) {
radioButtons.push({
id: 1,
name: "radiobutton",
value: "test"
});
return {
radioButtons: radioButtons
};
} else {
radioButtons.push({
id: radioButtons[radioButtons.length - 1].id + 1,
name: "raiodButton_" + (radioButtons[radioButtons.length - 1].id + 1),
value: radioButtons[radioButtons.length - 1].value
});
return {
radioButtons: radioButtons
};
}
});
};
removeBox = () => {
this.setState(prevstate => {
let radioButtons = prevstate.radioButtons;
if (radioButtons.length !== 0) {
radioButtons.pop(radioButtons[radioButtons.length - 1]);
return {
radioButtons: radioButtons
};
} else {
return { radioButtons: radioButtons };
}
});
};
render() {
return (
<div>
<div className="form-check">
{this.state.radioButtons.map(radiobutton => {
return (
<div>
<input
className="form-check-input"
type="radio"
id={radiobutton.id}
name={radiobutton.name}
value={radiobutton.value}
/>
<label className="form-check-label" for="">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
);
})}
</div>
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
<button
type="button"
className="btn btn-danger"
onClick={this.removeBox}
>
Remove Option
</button>
</div>
);
}
}
export default TextRadio;
https://codesandbox.io/embed/confident-browser-tmojp
I was playing around with your idea and made some changes in the code, just to show you an example, how you can dynamically create new components and store them in applications state and then render out to user based on their actions.
I created new component just for form UI: option, input field and remove button. If user clicks on the Add Option, new item of the component is added to application state and then render out. Remove button is used to remove Item from state.
class TextRadio extends Component {
state = {
optionInputs: []
};
addBox = () => {
const optionInputsUpdated = [
...this.state.optionInputs,
<OptionInput id={uuid.v4()} remove={this.removeBox} />
];
this.setState({ optionInputs: optionInputsUpdated });
};
removeBox = id => {
const optionInputsUpdated = this.state.optionInputs.filter(
item => item.props.id !== id
);
this.setState({ optionInputs: optionInputsUpdated });
};
render() {
return (
<div>
{this.state.optionInputs.map((optionInput, idx) => {
return (
<div key={idx} test="123">
{optionInput}
</div>
);
})}
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
</div>
);
}
}
const OptionInput = props => {
return (
<div className="form-check">
<input
className="form-check-input"
type="radio"
id=""
name="radio"
value=""
/>
<label className="form-check-label" for="">
<input className="form-control" type="text" placeholder="" />
</label>{" "}
<button
type="button"
className="btn btn-danger"
onClick={() => props.remove(props.id)}
>
Remove Option
</button>
</div>
);
};
Hope this gives you better understanding, how to achieve your goal.
If you need additional help, just post a comment under this answer, and I will update demo to help you.
Here is DEMO I created from your code: https://codesandbox.io/s/nice-ganguly-s4wls
first you have to initialize an empty array state
this.state={
radioButtons : [{input:''}]
}
then in your return statement you have to loop through the radioButtons array and show the radio button with input
{
this.state.radioButtons.map(item => (
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
))
}
then in your addBox function append an object on every click
addBox = () => {
this.setState({radioButtons:[...this.state.radioButtons, {input:''}]})
}
function to remove a radio button object
removeBox = () => {
let radioArray = this.state.radioButtons
radioArray.pop()
this.setState({radioButtons:radioArray})
}
Final code Looks like this :
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component{
constructor(props){
super(props);
this.state={
radioButtons :[{input:''}]
}
}
addBox = () => {
this.setState({radioButtons:[...this.state.radioButtons, {input:''}]})
}
removeBox = () => {
let radioArray = this.state.radioButtons
radioArray.pop()
this.setState({radioButtons:radioArray})
}
render(){
return(
<div>
{
this.state.radioButtons.map(item => (
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
))
}
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
<button type="button" className="btn btn-danger" onClick={this.removeBox}>
Remove Option
</button>
</div>
)
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
codepen Example

How to use Reactjs event handlers instead of jQuery event handlers on this select menu example?

this is my first question on StackOverflow, so please be patient.
I started learning ReactJS a few days ago and there are still a few things not really clear to me.
How to replace jQuery event handlers with ReactJS?
I'm working on this little select menu but I made it using jQuery and now I want to use it as a ReactJS component and I tried to manage the
$('.select').click(function(e) {
e.preventDefault();
e.stopPropagation();
$(this).toggleClass('expanded');
$('#'+$(e.target).attr('for')).prop('checked',true);
});
$(document).click(function() {
$('.select').removeClass('expanded');
});
Please check the full code here: https://codepen.io/Wael-Alsabbouh/pen/GvWvzv
This is what I have done in ReactJS but still not working properly!
import React from 'react';
export default class select extends React.Component {
/**
* Show and hide select options
*/
constructor(props) {
super(props);
this.state = { addClass: false, value: '', isToggleOn: true };
this.handleClick = this.handleClick.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn,
addClass: !this.state.addClass,
}));
}
handleChange(e) {
this.setState({
value: e.target.value,
});
e.preventDefault();
}
/**
* React render
*/
render() {
const classNames = ['select'];
if (this.state.addClass) {
classNames.push('expanded');
}
return (
<div className={classNames.join(' ')} >
<input type="radio" name="sortType" value={this.handleChange} checked="checked" id="selected-item" onClick={this.handleClick} /><label htmlFor="selected-item">Item 00</label >
<input type="radio" name="sortType" value={this.handleChange.value} onChange={this.handleChange} /><label htmlFor="Item01">Item 01</label>
<input type="radio" name="sortType" value={this.handleChange.value} onChange={this.handleChange} /><label htmlFor="Item02">Item 02</label>
<input type="radio" name="sortType" value={this.handleChange.value} onChange={this.handleChange} /><label htmlFor="Item03">Item 03</label>
<input type="radio" name="sortType" value={this.handleChange.value} onChange={this.handleChange} /><label htmlFor="Item04">Item 04</label>
<input type="radio" name="sortType" value={this.handleChange.value} onChange={this.handleChange} /><label htmlFor="Item05">Item 05</label>
</div>
);
}
}
Thank you in advance.
In less file remove this
&:nth-child(2) {
margin-top: 2em;
border-top: .06em solid #d9d9d9;
}
}
It'd be better to wrap the Radio button in its own higher order component and let it maintain its own state. I created a new Radio class(I'm not a creative namer) as an example.
/*
* A simple React component
*/
class Select extends React.Component {
constructor(props) {
super(props);
this.state = { addClass: false, value: '', isToggleOn: true };
this.handleClick = this.handleClick.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleClick() {
console.log("hello")
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn,
addClass: !this.state.addClass,
}));
}
handleChange(e) {
this.setState({
value: e.target.value,
});
e.preventDefault();
}
render() {
const classNames = ['select'];
if (this.state.addClass) {
classNames.push('expanded');
}
return <div className={classNames.join(' ')} onChange={this.handleChange}>
<input type="radio" name="sortType" value={this.handleChange.value} checked="checked" id="selected-item" onClick={this.handleClick} /><label htmlFor="selected-item">Item 00</label>
<Radio name={"Item01"}/>
<Radio name={"Item02"}/>
<Radio name={"Item03"}/>
<Radio name={"Item04"}/>
<Radio name={"Item05"}/>
</div>
}
}
class Radio extends React.Component {
constructor(props) {
super(props);
this.state = { isOn:props.isOn?true:false };
this.toggleState=this.toggleState.bind(this)
}
toggleState(){
console.log("Look at me I'm changing my own state for "+this.props.name+"!!!!")
this.setState({isOn:!this.state.isOn})
}
render() {
return <span><input type="radio" name="sortType" value={this.state.isOn} /><label onClick={this.toggleState} htmlFor={this.props.name}>{this.props.name}</label></span>
}
}
/*
* Render the above component into the div#app
*/
React.render(<Select />, document.getElementById('app'));

how to display the table using react js

Im new to reactjs and Im just trying to create a page with the userName and password. When the submit is clicked it should display a list of table names in the same page. For this I have two react components, placed it in a separate js file. So when the button is clicked the table names should be generated. I have tried a sample code but I'm unable to display the list. So looking for help in reactjs.
tableContent.js
import React from 'react';
class tableContent extends React.Component {
render() {
return (
<select name="sometext" multiple="multiple">
<option>Table1</option>
<option>Table2</option>
<option>Table3</option>
<option>Table4</option>
<option>Table5</option>
</select>
)
}
}
export default tableContent;
login.js
import React from 'react';
import tableContent from './tables';
class Login extends React.Component{
constructor(){
super();
this.state={
showComponent : false,
};
this.buttonClick = this.buttonClick.bind(this);
}
buttonClick(){
this.setState({
showComponent: true,
})
}
render(){
return(
<div>
<form>
<label>userName :</label>
<input type="text" />
<br/>
<label>Password :</label>
<input type="text" />
<button onClick={this.buttonClick.bind(this)}> Submit </button>
</form>
<tableContent />
</div>
)
}
}
export default Login;
Change the Name tableContent to TableContent, because name of the react component must start will upper case letter otherwise it will be treated as html element.
Use e.preventDefault(); inside buttonClick function to prevent the form submission automatically.
Check the working code:
class Login extends React.Component{
constructor(){
super();
this.state={
showComponent : false,
};
}
buttonClick(e){
e.preventDefault();
this.setState({
showComponent: true,
})
}
render(){
return(
<div>
<form>
<label>userName :</label>
<input type="text" />
<br/>
<label>Password :</label>
<input type="text" />
<button onClick={this.buttonClick.bind(this)}> Submit </button>
</form>
{this.state.showComponent && <TableContent />}
</div>
)
}
}
class TableContent extends React.Component {
render() {
return (
<select name="sometext" multiple="multiple">
<option>Table1</option>
<option>Table2</option>
<option>Table3</option>
<option>Table4</option>
<option>Table5</option>
</select>
)
}
}
ReactDOM.render(<Login/>, 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'/>

Categories