I am working on a very basic form in React, and I am having difficulty getting the data to submit properly. In this current setup, only the 'content' field is submitting correctly, eventhough the firstName, lastName, and email are all written the same. The radio buttons and dropdown are also not submitting. Any ideas?
import React from "react";
import axios from "axios";
import '../ticket.min.css'
class Ticket extends React.Component {
constructor(props) {
super(props);
this.state = {
firstName: '',
lastName: '',
email: '',
content: ''
}
this.ticketName = React.createRef();
this.state = { tickets: [] };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.onValueChange = this.onValueChange.bind(this);
}
handleChange = event => {
this.setState({ value: event.target.value });
}
handleSubmit = event => {
alert('Your ticket has been submitted');
event.preventDefault();
}
onValueChange = event => {
this.setState({
selectedOption: event.target.value
});
}
addTicket = () => {
let url = "http://localhost:8080/tickets";
axios.post(url, { firstName: this.ticketName.current.value, lastName: this.ticketName.current.value, email: this.ticketName.current.value, content: this.ticketName.current.value }).then(response => {
this.ticketName.current.value = "";
alert('Your ticket has been submitted');
});
};
getData = () => {
let url = "http://localhost:8080/tickets";
axios.get(url).then(response => this.setState({ tickets: response.data }));
};
render() {
return (
<div>
<form>
<label>First Name:</label>
<input ref={this.ticketName} type="text" name="firstName"/><br></br>
<label>Last Name:</label>
<input ref={this.ticketName} type="text" name="lastName"/><br></br>
<label>Email:</label>
<input ref={this.ticketName} type="text" name="email"/><br></br>
</form>
<form onSubmit={this.handleSubmit}>
<label>
Select a Category:<br></br>
<select value={this.state.value} onChange={this.handleChange}>
<option value="hardware">Hardware</option>
<option value="software">Software</option>
<option value="internet">Internet</option>
<option value="other">Other</option>
</select>
</label>
</form>
<form>
<label>Please Describe Your Issue:</label><br></br>
<textarea name="content" ref={this.ticketName}/>
</form>
<form onSubmit={this.handleSubmit}>
<label>
Select the Urgency Level:<br></br>
<input type="radio" value="Urgent" checked={this.state.selectedOption === "Urgent"} onChange={this.onValueChange} />Urgent<br></br>
<input type="radio" value="Normal" checked={this.state.selectedOption === "Normal"} onChange={this.onValueChange} />Normal<br></br>
<input type="radio" value="Low Priority" checked={this.state.selectedOption === "Low Priority"} onChange={this.onValueChange} />Low Priority
</label>
</form>
<form>
<button type="button" className="btn btn-primary" onClick={this.addTicket}>Submit</button>
</form>
<h3>Pending Tickets</h3>
<button type="button" className="btn btn-primary" onClick={this.getData}>Show Pending</button>
<ul>
{this.state.tickets.map(p => (
<li key={p.id}>
{p.firstName}{p.lastName}
{/* {p.firstName} : { p.complete ? "complete" : "not complete" } <button type="button" className="btn btn-success">Complete</button><button type="button" className="btn btn-danger">Delete</button> */}
</li>
))}
</ul>
</div>
);
}
}
export default Ticket;
You should put fields in one form element and set the button type to submit.
Related
I need help by a simple question:
how i can use two select forms on one site with one handleChange function? i have two select forms but every-time i am using one after the other one the value will be overwritten. Should i separate the handleChange function? I dont want to work with an npm like react select. Is anyone able to help me out here? Im really stuck on this
import React from "react";
import axios from "./axios.js";
import { useState } from "react";
import Select from "react-select";
import Creatives from "./creatives";
import FormatType from "./formattype";
export default class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "",
value1: "",
manager: "",
gpNummer: "",
caNummer: "",
gpNummer: "",
advertiser: "",
agency: "",
campaignName: "",
formatType: "",
startDate: "",
creative: "",
enddate: "",
error: false,
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
updateField(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
/*
submit1() {
axios
.post("/Login", { mail: this.state.mail, password: this.state.password })
.then((response) => {
console.log(response.data);
if (response.data.success) {
/*location.replace('/');
} else {
this.setState({ error: response.data.error });
}
});
}
submit2() {
axios
.post("/Login", { mail: this.state.mail, password: this.state.password })
.then((response) => {
console.log(response.data);
if (response.data.success) {
/*location.replace('/');
} else {
this.setState({ error: response.data.error });
}
});
}
*/
handleChange(e) {
this.setState({ value: e.target.value });
}
handleSubmit(e) {
const {
gpNummer,
caNummer,
advertiser,
creative,
agency,
campaignName,
formatType,
startDate,
enddate,
} = this.state;
e.preventDefault();
}
render() {
return (
<div className="Main">
<div className="allforms">
<span id="Linetitle">New LineItem:</span>
{this.state.error && <div className="error">{this.state.error}</div>}
<label> Manager </label>
<select manager={this.state.manager} onChange={this.handleChange}>
<option manager="Katja">Katja</option>
<option manager="Seba">Seba</option>
<option value="aylina">aylina</option>
<option value="Christina">Christina</option>
</select>
<label> GP-Nummer </label>
<input
type="text"
onChange={(e) => this.updateField(e)}
name="gpNummer "
placeholder=" GP-Nummer "
/>
<label> CA-Nummer </label>
<input
type="text"
onChange={(e) => this.updateField(e)}
name="caNummer "
placeholder=" Fill in CA-Nummer "
/>
<label> Werbetreibender </label>
<input
type="text"
onChange={(e) => this.updateField(e)}
name="advertiser"
placeholder=" Fill in Werbetreibender "
/>
<label> Agentur </label>
<input
type="text"
onChange={(e) => this.updateField(e)}
name="agency "
placeholder=" Fill in Agentur"
/>
<label> Media Campaign Name </label>
<input
type="text"
onChange={(e) => this.updateField(e)}
name="campaignName "
placeholder=" Fill in Campaign Name"
/>
<label> Formattyp </label>
{/* <div className="select"> <FormatType /></div>*/}
<select value1={this.state.creative} onChange={this.handleChange}>
<option value1="MR">MR</option>
<option value1="premiumAdbundle">premiumAdbundle</option>
<option value1="adBundle">AdBundle</option>
<option value1="fireplace">Fireplace</option>
</select>
<label> Creative </label>
<select value={this.state.formatType} onChange={(e)=>this.handleChange(e)}>
<option value="native">native</option>
<option value="display">display</option>
<option value="advertorial">advertorial</option>
<option value="mobile">mobile</option>
</select>
{/*<div className="select"><Creatives /></div>*/}
<label>Start Date </label>
<input
type="date"
onChange={(e) => this.updateField(e)}
name="startDate"
placeholder=" Fill in Formattyp"
/>
<label>End Date </label>
<input
type="date"
onChange={(e) => this.updateField(e)}
name="enddate"
placeholder=" Fill in Formattyp"
/>
<input
onClick={(e) => this.submit1(e)}
type="submit"
value="Save to List"
/>
<input
onClick={(e) => this.submit2(e)}
type="submit"
value="Push to gam"
/>
</div>
</div>
);
}
}
You can write your handlechange this way :
onChange={e => this.handleChange(e, customParam)}>
This way, you can add a condition check on your handlechange function on the second parameter, and change behaviour as needed.
As someone already suggested, you can write a single function that accepts two parameters (the event and the state that you change).
Also, if you want, you can use a single State, but as an Array. In you case you can create the state like this:
this.state{
Form: {
State1: '',
State2: '',
},
// other states
}
and then you can access to a single state with Form.State1.
So, you can write a function like the following one to update the single state:
const updateField = (name, value) => {
//Change the state with the new field updated
const newData = { ...Form, [name]: value };
this.setState({Form: newData});
};
And on the single component, to update the state, you have to call on onChange, I show you an example with input:
<input
type="text"
onChange={(e) => this.updateField(e)}
name="gpNummer "
placeholder=" GP-Nummer "
value={this.state.Form.State1}
onChange={ev => updateField(ev.target.name, ev.target.value)}
/>
I am following along with this tutorial (https://medium.com/#beaucarnes/learn-the-mern-stack-by-building-an-exercise-tracker-mern-tutorial-59c13c1237a1) and am trying to print to console through the onSubmit function but this is not occurring and I do not know why. I've made sure to use the bind method, and everything seems to be referenced correctly. What am I missing here?
import React, {Component} from 'react';
import DatePicker from 'react-datepicker';
import "react-datepicker/dist/react-datepicker.css";
export default class CreateWorkout extends Component {
constructor(props) {
super(props); // Refers to the parent class constructorq
this.onChangeUsername = this.onChangeUsername.bind(this);
this.onChangeDescription = this.onChangeDescription.bind(this);
this.onChangeReps = this.onChangeReps.bind(this);
this.onChangeDuration = this.onChangeDuration.bind(this);
this.onChangeDate = this.onChangeDate.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
username:'',
description: '',
reps: 0,
duration: 0,
date: new Date(),
users: []
}
}
componentDidMount() { // Invoked immediately after a component is mounted
this.setState({
users: ['test user'],
username: 'test user'
});
}
onChangeUsername(e) {
this.setState({
username: e.target.value
});
}
onChangeDescription(e) {
this.setState({
description: e.target.value
});
}
onChangeReps(e) {
this.setState({
reps: e.target.value
});
}
onChangeDuration(e) {
this.setState({
duration: e.target.value
});
}
onChangeDate(date) { // Need to add a date picker library for this
this.setState({
date: date
});
}
// Submit method for submitting an event of the form...
onSubmit(e) {
e.preventDefault();
const workout = {
username: this.state.username,
description: this.state.description,
reps: this.state.reps,
duration: this.state.duration,
date: this.state.date,
};
console.log(workout);
window.location = '/'; // After form is submitted, the location is updated so the user is taken back to the home page
}
render() {
return (
<div>
<h3>Create New Workout Log</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Username: </label>
<select ref="userInput" required className="form-control" value={this.state.username} onChange={this.onChangeUsername}>
{
this.state.users.map(function(user) {
return <option key={user} value={user}>{user}</option>;
})
}
</select>
</div>
<div className="form-group">
<label>Description: </label>
<input type="text" required className="form-control" value={this.state.description} onChange={this.onChangeDescription}/>
</div>
<div className="form-group">
<label>Reps: </label>
<input type="text" className="form-control" value={this.state.reps} onChange={this.onChangeReps}/>
</div>
<div className="form-group">
<label>Duration: </label>
<input type="text" className="form-control" value={this.state.duration} onChange={this.onChangeDuration}/>
</div>
<div className="form-group">
<label>Date: </label>
<div><DatePicker selected={this.state.date} onChange={this.state.onChangeDate}/></div>
</div>
<div className="form-group">
<input type="submit" value="Create Workout Log" className="btn btn-primary"/>
</div>
</form>
</div>
);
}
}
I am created a dynamic form in react.js but i can not type anything value in input because onchnage function not working i don't know why i tried a lot of times but i am getting failed and adding form and deleting form is working all right only input value not working here is my code and codesandbox link https://codesandbox.io/s/reactdynamicform-02cho .
import React, { Component } from "react";
import "bootstrap/dist/css/bootstrap.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
inputFields: [
{
firstName: "",
lastName: ""
}
]
};
}
handleAddFields = () => {
const values = this.state.inputFields;
values.push({ firstName: "", lastName: "" });
this.setState({
values
});
};
handleRemoveFields = index => {
const values = this.state.inputFields;
values.splice(index, 1);
this.setState({
values
});
};
async onChange(e, index) {
if (
["firstName","lastName"].includes(e.target.name)
) {
let cats = [...this.state.inputFields];
cats[index][e.target.name] = e.target.value;
await this.setState({
cats
});
}else{
this.setState({ [e.target.name]: e.target.value.toUpperCase() });
}
console.log(this.state.inputFields);
}
handleSubmit = e => {
e.preventDefault();
console.log("inputFields", this.state.inputFields);
};
render() {
return (
<>
<h1>Dynamic Form Fields in React</h1>
<form onSubmit={this.handleSubmit.bind(this)}>
<div className="form-row">
{this.state.inputFields.map((inputField, index) => (
<div key={`${inputField}~${index}`}>
<div className="form-group col-sm-6">
<label htmlFor="firstName">First Name</label>
<input
type="text"
className="form-control"
id="firstName"
name="firstName"
value={inputField.firstName}
onChange={this.onChange.bind(index)}
/>
</div>
<div className="form-group col-sm-4">
<label htmlFor="lastName">Last Name</label>
<input
type="text"
className="form-control"
id="lastName"
name="lastName"
value={inputField.lastName}
onChange={this.onChange.bind(index)}
/>
</div>
<div className="form-group col-sm-2">
<button
className="btn btn-link"
type="button"
onClick={() => this.handleRemoveFields(index)}
>
-
</button>
<button
className="btn btn-link"
type="button"
onClick={() => this.handleAddFields()}
>
+
</button>
</div>
</div>
))}
</div>
<div className="submit-button">
<button
className="btn btn-primary mr-2"
type="submit"
// onSubmit={this.handleSubmit}
>
Save
</button>
</div>
<br />
<pre>{JSON.stringify(this.state.inputFields, null, 2)}</pre>
</form>
</>
);
}
}
export default App;
You approach is not the correct. Use object to contain form values
state = {
inputFields: { firstName: '', lastName: '' }
}
onChange = (e) => {
const { name, value } = e.target;
this.setState(prevState => ({ inputFields: { ...prevState.inputFields, [name]: value } }));
}
// in jsx
<input name="firstName" onChange={this.onChange} />
try this
onChange={(e)=>{this.onChange(e, index)}}
instead of
onChange={this.onChange.bind(index)}
1) Since your inputFields state is an array, you can't just call this.state.inputFields.firstName and even less inputField.firstName.
You have to call this.state.inputsFields[0].firstName.
2) If you want the index AND the event, you have to pass the onChange event like this :
<input
type="text"
className="form-control"
id="lastName"
name="lastName"
onChange={event => this.handleChange(event, index)}
/>
handleChange = (event, index) => {
console.log(event.currentTarget.value, index);
};
// output : {whatever you type} {index of the form}
// exemple : "hello 1"
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
I have three inputs, and I want each input's data to be stored in a state. For example, the name input should be stored in the name state, because I'll need it later to push the three states' values in a firebase database.
I used the onChange function to store the data, but I didn't know how to make each input's function relative to the state I want to put it in.
import React from "react";
import ReactDOM from "react-dom";
export default class Inputs extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "",
email: "",
age: ""
};
}
handleChange = e => {
this.setState({ name: e.target.value });
};
render() {
return (
<div>
<form>
<label>
name:
<input type="text" name="name" onChange={this.handleChange} />
</label>
<label>
email:
<input type="text" name="email" onChange={this.handleChange} />
</label>
<label>
age:
<input type="text" name="age" onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
<textarea value={this.state.value} onChange={this.handleChange} />
<button onClick={() => this.props.onClick(this.state.value)}>
Add task
</button>
</div>
);
}
}
getChanges = (e) => {
console.log(e);
this.setState({[e.target.name]: e.target.value}, function () {
console.log(this.state)
})
};
call this function,
<Input onChange={(e) => this.getChanges(e)} name={'name'}
value={this.state.name} placeholder={'Name'}/>
You can pass key and value
<input type="text" name="name" onChange={(event)=>this.handleChange(event,'name')} />
and in your function you can do something like this
handleChange = (e,key) => {
this.setState({ [key] : e.target.value });
};