I am working on form which have combination of input field and radio button. Whenever I select the radio button, it is not getting selected but value is getting update in form state . For some reason, radio button is not showing selected
const InputForm = () => {
const [form, setForm] = useState({name: "", job: "no" });
const {name, job} = form;
const handleJob = (e) => {
let value = e.target.value;
setForm({ ...form, job: value });
};
const onInputChange = (e) => {
setForm({...form, [e.target.name]: e.target.value});
}
return (
<>
<input
type="text"
className="form-control input-text-box"
placeholder="Name"
value={name}
onChange={onInputChange}
/>
<div className="form-check-inline mx-2">
<input
type="radio"
className="form-check-input"
name="radioOption"
value="yes"
onChange={handleJob}
checked={job === "yes"}
/>{" "}
<label className="form-check-label" for="radioOption">
Yes
</label>
<input
type="radio"
name="radioOption"
className="form-check-input"
value="no"
onChange={handleJob}
checked={job === "no"}
/>{" "}
<label className="form-check-label" for="radioOption">
No
</label>
</div>
</>
);
};
export default InputForm;
Related
I am new to react and I got a scenario where I have multiple checkboxes on my form. I want the user to check all the checkboxes only then enable the submit button on the form. On Load, the submit button will be disabled. How to do this?
Here is the code that I have written so far:
const MultipleCheckboxes = () => {
const handleChange = () => {
}
const allChecked = () => {
}
return (
<div>
<form>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value="Java"
id="languageChkDefault"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Javascript
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value="Angular"
id="languageChkDefault"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Angular
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value="Python"
id="languageChkDefault"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Python
</label>
</div> <br />
<button disabled={!allChecked}>Submit</button>
</form>
</div>
);
};
export default MultipleCheckboxes;
Can anybody help me on this? thank you
This is my solution, I hope it helps you
import { useState, useEffect } from "react";
const MultipleCheckboxes = () => {
const [allChecked, setAllChecked] = useState(false);
const [checkboxes, setCheckboxes] = useState({
javaCheckbox: false,
angularCheckbox: false,
pythonCheckbox: false
});
function handleChange(e) {
setCheckboxes({
...checkboxes,
[e.target.id]: e.target.checked
})
}
useEffect(() => {
const result = Object.values(checkboxes).every(v => v);
console.log(result);
setAllChecked(result);
}, [checkboxes]);
return (
<div>
<form>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value={checkboxes.javaCheckbox}
id="javaCheckbox"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Javascript
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value={checkboxes.angularCheckbox}
id="angularCheckbox"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Angular
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value={checkboxes.pythonCheckbox}
id="pythonCheckbox"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Python
</label>
</div> <br />
<button disabled={!allChecked}>Submit</button>
</form>
</div>
);
};
export default MultipleCheckboxes;
You can use react useState hook and set its default value to false.
const [state, setstate] = useState(false)
When the user clicks on an input box set the state to true. You may encounter some problems when the user unchecks the box, so you can use an if statement to handle state change
For example:
if (state === true){
setstate(false)
}else{
setstate(true)
}
or you can just use this code inside the handleChange function:
!state
It inverses the state to true/false accordingly.
After that you can use a ternary operator inside the component to check whether the user has checked all the boxes, if the user hasn't checked all the boxes, disable the button or else do otherwise.
For example, if the state is true (or in other words, if the user has checked the box), render the normal styled button, else render the disabled button:
{state? <button className = "styled"/>: <button disabled className="styled"/>}
Of course, I have only checked the state of one input box. Now you can simply check for multiple conditions by declaring multiple states for each box.
{state1 && state2 && state3 ? <button className = "styled"/>: <button disabled className="styled"/>}
If you are not yet familiar with ternary operators, you should go through this doc Ternary operators.
If you haven't heard of useState and react hooks yet, feel free to look the React's documentation. Welcome to the React ecosystem!
i a new user and a new in React world. I need help to solve this situation about a Select with values from mysql DB.
I receive the values, but the select goes in infinite loop.
The error is surely in this file cause server.js works without problem!!
Really thanks for the help, and sorry if it could be a stupid question. I m studying react from one week and i have not found answers on internet
function FormAddMenu({ registerMenu }) {
const [nomeMenuReg, setNomeMenuReg] = useState("");
const [descrizioneMenuReg, setDescrizioneMenuReg] = useState("");
const [prezzoMenuReg, setPrezzoMenuReg] = useState("");
const [disponibilitaMenuReg, setDisponibilitaMenuReg] = useState("");
const [portataMenuReg, setPortataMenuReg] = useState("");
const [addMenu, setAddMenu] = useState({
portataMenuReg: "",
nomeMenuReg: "",
descrizioneMenuReg: "",
prezzoMenuReg: "",
disponibilitaMenuReg: "",
});
const [portate, setPortate] = useState({ value: "", label: "" });
const selectOptions = async () => {
Axios.post("http://localhost:3001/selectPortata").then((response) => {
// console.log("risposta:",response.data)
setPortate(
response.data.map((risp) => ({
...setPortate,
value: risp.value,
label: risp.label,
})),
);
});
};
selectOptions();
console.log("portate:", portate);
const submitHandler = (e) => {
e.preventDefault();
registerMenu(addMenu);
document.getElementById("addmenu").reset();
};
const handleCheckbox = (e) => {
console.log(e.target.checked);
if (e.target.checked === true) {
setAddMenu({ ...addMenu, disponibilitaMenuReg: 1 });
} else {
setAddMenu({ ...addMenu, disponibilitaMenuReg: e.target.value });
}
};
return (
<div className="container width85">
<h1>CREA IL MENU'</h1>
<form id="addmenu">
<div className="mb-3">
<label htmlFor="portataMenuReg" className="form-label">
PORTATA
</label>
<Select
options={portate}
onChange={(e) => setAddMenu({ ...addMenu, portataMenuReg: e.target.value })}
className="mb-3"
/>
</div>
<div className="mb-3">
<label htmlFor="nomeMenuReg" className="form-label">
NOME
</label>
<input
type="text"
onChange={(e) => setAddMenu({ ...addMenu, nomeMenuReg: e.target.value })}
className="form-control"
id="nomeMenuReg"
rows="3"
/>
</div>
<div className="mb-3">
<label htmlFor="descrizioneMenuReg" className="form-label">
DESCRIZIONE
</label>
<textarea
className="form-control"
onChange={(e) =>
setAddMenu({ ...addMenu, descrizioneMenuReg: e.target.value })
}
id="descrizioneMenuReg"
rows="3"
></textarea>
</div>
<div className="mb-3">
<label htmlFor="prezzoMenuReg" className="form-label">
PREZZO
</label>
<input
type="text"
className="form-control"
onChange={(e) => setAddMenu({ ...addMenu, prezzoMenuReg: e.target.value })}
id="prezzoMenuReg"
rows="3"
/>
</div>
<div className="mb-3">
<label htmlFor="disponibilitaMenuReg" className="form-label">
DISPONIBILITA'
</label>
<input
type="checkbox"
value="0"
className="htmlForm-control"
onChange={handleCheckbox}
id="disponibilitaMenuReg"
rows="3"
/>
</div>
<div className="mb-3">
<button type="submit" onClick={submitHandler} className="btn btn btn-danger">
AGGIUNGI AL MENU
</button>
</div>
</form>
</div>
);
}
export default FormAddMenu;
Wrap the selectOptions(); call in an useEffect (since loading data and mutating state based on it is a side effect).
The empty dependency array (documented above) means the effect is only executed once on mount.
React.useEffect(() => {
selectOptions();
}, []);
Originally, I designed this component to have a useState for each individual input. After realizing that this would not be the best approach for adding new inputs, I refactored to use only one useState. I'm able to get the values for all, but gender. I'm hoping someone could point me in the right direction.
Note: I realize it's not picking up the value because I'm not using person.gender. I went ahead and tried to add value={person.gender = "the value I want"} for each input.
const Forms = () => {
const [person, setPerson] = useState({
firstName: "",
lastName: "",
age: "",
gender: "",
email: "",
});
const [people, setPeople] = useState([]);
const handleChange = (e) => {
const name = e.target.name;
const value = e.target.value;
setPerson({ ...person, [name]: value });
};
const handleSubmit = (e) => {
e.preventDefault();
if (person.firstName && person.lastName && person.age && person.email) {
const newPerson = {
...person,
id: new Date().getTime().toString(),
};
setPeople([...people, newPerson]);
setPerson({
firstName: "",
lastName: "",
age: "",
gender: "",
email: "",
});
}
};
console.log(person.gender);
return (
<article>
<h2>Forms</h2>
<form className="form">
<div className="form-control">
<label htmlFor="firstName">First Name:</label>
<input
type="text"
id="firstName"
name="firstName"
value={person.firstName}
onChange={handleChange}
/>
</div>
<div className="form-control">
<label htmlFor="lastName">Last Name:</label>
<input
type="text"
id="LastName"
name="lastName"
value={person.lastName}
onChange={handleChange}
/>
</div>
<div className="form-control">
<label htmlFor="age">Age:</label>
<input
type="text"
id="age"
name="age"
value={person.age}
onChange={handleChange}
/>
</div>
<div className="form-control">
<label htmlFor="gender">Gender:</label>
<select onChange={handleChange} id="gender">
<option name="gender" value="male">
Male
</option>
<option name="gender" value="female">
Female
</option>
<option name="gender" value="prefer not to answer">
prefer not to answer
</option>
</select>
</div>
<div className="form-control">
<label htmlFor="email">Email:</label>
<input
type="email"
id="email"
name="email"
value={person.email}
onChange={handleChange}
/>
</div>
<button type="submit" className="btn" onClick={handleSubmit}>
Submit
</button>
</form>
{people.map((person) => {
const { firstName, lastName, age, gender, email, id } = person;
return (
<div className="item" key={id}>
<h4>
{firstName} {lastName}
</h4>
<span>{age}</span>
<span>{gender}</span>
<p>{email}</p>
</div>
);
})}
</article>
);
};
export default Forms;
Thanks,
Sean
You have to give the name attribute to the select element, not to its options
<select name="gender" onChange={handleChange} id="gender">
Try reading documentation in react about forms
https://reactjs.org/docs/forms.html
Another thing I think it e.target.value is not working in select form, also you shoud use independent state for every form input because in this layer you cause some effect and rerender
This question already has answers here:
Handle change event of all input fields without using refs
(2 answers)
Closed 2 years ago.
I have several inputs ,Each of the inputs has its own value .How can I have a function for (onChange) all of them ?
For example
handleChange1(event) {
this.setState({value1: event.target.value});
}
handleChange2(event) {
this.setState({value2: event.target.value});
}
}
handleChange3(event) {
this.setState({value3: event.target.value});
}
<input type="text" value={this.state.value1} onChange={this.handleChange1} />
<input type="text" value={this.state.value2} onChange={this.handleChange2} />
<input type="text" value={this.state.value3} onChange={this.handleChange3} />
I just want to have one handleChange
When you need to handle multiple controlled input elements, you can add a name attribute to each element and let the handler function choose what to do based on the value of event.target.name.
For example:
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
return (
<form>
<label>
value1:
<input
name="value1"
type="checkbox"
checked={this.state.value1}
onChange={this.handleInputChange} />
</label>
<br />
<label>
value2:
<input
name="value2"
type="number"
value={this.state.value2}
onChange={this.handleInputChange} />
</label>
<br />
<label>
value3:
<input
name="value3"
type="text"
value={this.state.value3}
onChange={this.handleInputChange} />
</label>
</form>
);
}
}
If you add a name to the input you can use that off of the event.
handleChange1(event) {
const {name, value} = event.target
this.setState({[name]: value});
}
<input name="inputone" type="text" value={this.state.value1} onChange={this.handleChange1} />
<input name="inputtwo" type="text" value={this.state.value2} onChange={this.handleChange2} />
<input name="inputthree" type="text" value={this.state.value3} onChange={this.handleChange3} />
You can simply do by using input name:
Code:
import React from "react";
import "./styles.css";
class MyComponent extends React.Component {
state = {
value1: "",
value2: "",
value3: ""
};
handleChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
};
render() {
console.log(this.state);
return (
<>
<input
name="value1"
value={this.state.value1}
type="text"
value={this.state.value1}
onChange={this.handleChange}
/>
<input
name="value2"
value={this.state.value2}
type="text"
value={this.state.value2}
onChange={this.handleChange}
/>
<input
name="value3"
value={this.state.value3}
type="text"
value={this.state.value3}
onChange={this.handleChange}
/>
</>
);
}
}
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<MyComponent />
</div>
);
}
Demo: https://codesandbox.io/s/beautiful-brook-p46zs?file=/src/App.js:0-1092
i always do this by switch case
handleChange(event) {
switch (event.target.name) {
case 'name1':
this.setState({ name1: event.target.value });
break;
case 'name2':
this.setState({ name2: event.target.value });
break;
case 'name3':
this.setState({ name3: event.target.value });
break;
default:
break;
}
}
<input type="text" name="name1" value={this.state.value1} onChange={this.handleChange1} />
<input type="text" name="name2" value={this.state.value2} onChange={this.handleChange2} />
<input type="text" name="name3" value={this.state.value3} onChange={this.handleChange3} />
You can use react hooks useState for each field:
const [value1,setvalue1] = useState();
<input type="text" value={value1} onChange={(e)=>setvalue1(e.target.value)}/>
You still do have handle change to each input but you write less code.
You can also look here for more info about react hooks: https://reactjs.org/docs/hooks-state.html
If all inputs are same, I think we can render them dynamically so we don't need to repeat ourself and also make the code more clean.
I think we can have an array of inputs then render dynamically. By using closure, we can have one handleChange function for all inputs.
state={
inputValues: []
}
handleChange(index){
return (event)=>{
this.state.inputValues[index] = event.target.value;
this.setState({inputValues: this.state.inputValues})
}
}
render(){
return this.states.inputValues.map((inputValue, index)=>
<input type="text" value={inputValue} onChange={this.handleChange(index)} />
)
}
I'm having difficulty understanding how to handle radio buttons in forms with other types of inputs in React. I'm working from an example that incorporates string type input fields and another for pure radio buttons, but not sure how to get them to play nice together. The text field inputs work fine, but I can't get the radio button feature to work.
The basic theory behind the radio button of the React portion of this form is the checkbox for each option is set when a user clicks on a button and the checked value for that particular button is set to true via a logic check, while the other radio buttons are set to false.
I'm not sure how to integrate the handling of the input fields with the radio buttons.
Any guidance on this would be great!
Here's my form jsx:
class Project_form extends React.Component {
handleChange(e) {
const name = e.target.name;
const obj = {};
obj[name] = e.target.value;
this.props.onUserInput(obj);
}
handleOptionChange(e) {
const name = e.target.id;
const obj = {};
obj[name] = e.target.checked;
this.props.onChangeInput(obj);
}
handleSubmit(e) {
e.preventDefault();
this.props.onFormSubmit();
}
render() {
return (
<form onSubmit={(event) => this.handleSubmit(event)} >
<div className="form-group">
<input
id="project_name"
className="form-control"
type="text"
name="project_name"
placeholder="Enter Your Project Name"
value={this.props.project_name}
onChange={(event) => this.handleChange(event)} />
</div>
<div className="form-group">
<input
id="project_zipcode"
className="form-control"
type="text"
name="project_zipcode"
placeholder="Zipcode"
value={this.props.project_zipcode}
onChange={(event) => this.handleChange(event)} />
</div>
<div className="form-group">
<label>How Soon Do You Want this Project Started?</label>
<div className="radio">
<p><input type="radio"
value="1-2 Weeks"
name="project_timeframe"
id="project_timeframe_1-2_weeks"
checked={this.props.project_timeframe === 'ASAP'}
onChange={(event) => this.handleOptionChange(event)} />
<label>As Soon As Possible</label></p>
<p><input type="radio"
value="2-4 Weeks"
name="project_timeframe"
id="project_timeframe_2-4_weeks"
checked={this.props.project_timeframe === '2-4 Weeks'}
onChange={(event) => this.handleOptionChange(event)} />
<label>2-4 Weeks</label></p>
<p><input type="radio"
value="4-6 Weeks"
name="project_timeframe"
id="project_timeframe_4-6_weeks"
checked={this.props.project_timeframe === '4-6 Weeks'}
onChange={(event) => this.handleOptionChange(event)} />
<label>4-6 Weeks</label></p>
<p><input type="radio"
value="More Than 6 Weeks"
name="project_timeframe"
id="project_timeframe_more_than_6_weeks"
checked={this.props.project_timeframe === 'More Than 6 Weeks'}
onChange={(event) => this.handleOptionChange(event)} />
<label>More Than 6 Weeks</label></p>
</div>
</div>
<div className="form-group">
<input
type="submit"
value="Create Project"
className="btn btn-primary btn-lg"
/>
</div>
</form>
)
}
}
Here's my main component, which sets the state of the app.
class Projects extends React.Component {
constructor(props) {
super(props)
this.state = {
projects: this.props.projects,
project_name: '',
project_zipcode: '',
selectedTimeframeOption: 'ASAP'
}
}
handleUserInput(obj) {
this.setState(obj);
}
handleChangeInput(obj) {
this.setState({
selectedOption: obj.target.value
});
}
handleFormSubmit() {
const project = {
name: this.state.project_name,
zipcode: this.state.project_zipcode,
timeframe: this.state.project_timeframe
};
$.post('/projects',
{project: project})
.done((data) => {
this.addNewProject(data);
});
}
addNewProject(project){
const projects = update(this.state.projects, { $push: [project]});
this.setState({
projects: projects.sort(function(a,b){
return new Date(a['updated_at']) - new Date(b['updated_at']);
})
});
}
render() {
return (
<div>
<h2>Start a New Project</h2>
<a href="/projects/new/"
className="btn btn-large btn-success">Create a New Project</a>
{/* <%= link_to "Create a New Project", new_project_path, class: "btn btn-large btn-success" %> */}
<Project_form
project_name={this.state.project_name}
project_zipcode={this.state.project_zipcode}
project_timeframe={this.state.selectedTimeframeOption}
onUserInput={(obj) => this.handleUserInput(obj)}
onFormSubmit={() => this.handleFormSubmit()} />
{/* <% if #current_user.projects.any? %> */}
<div className="col-md-12">
<h3>Existing Projects</h3>
<div className="table-responsive">
<Project_list projects={this.state.projects} />
</div>
</div>
</div>
)
}
}
Ok, figured it out. Had to play around with getting the event object into the stateful component.
My form file now has this event handler added:
handleOptionChange(e) {
const option = e.target.name;
const obj = {};
obj[option] = e.target.value;
this.props.onUserInput(obj);
}
Then this.props.onUserInput(obj); gets called by the existing method in the Project.jsx file and I got rid of the handleChangeInput method.
handleUserInput(obj) {
this.setState(obj);
}
The state then flows down to the Project_form Component here:
<Project_form
project_name={this.state.project_name}
project_zipcode={this.state.project_zipcode}
project_timeframe={this.state.project_timeframe}
onUserInput={(obj) => this.handleUserInput(obj)}
onFormSubmit={() => this.handleFormSubmit()} />