I am trying to submit a form in react js I have multiple files
this.state = {
allValues: [],
};
changeHandler = (e) => {
this.setState({ ...this.allValues, [e.target.name]: e.target.value });
};
onsubmbit = (e) => {
e.preventDefault();
console.log(this.state.allValues);
};
<form onSubmit={this.onsubmbit}>
<input type='text' name='bloodsugar' onChange={this.changeHandler} value='' />
<input
type='text'
name='bloodpressure'
onChange={this.changeHandler}
value=''
/>
<button type='submit' style={styles.subbtn}>
Submit
</button>
</form>;
I am trying to submit a form in react js I have multiple files
I am trying to submit this form
console.log(this.state.allValues); when i console log it in submit function i want data as
{
bloodsugar:data of bloodsugar,
bloodpressure:data of bloodsugar,
}
when I console log it in submit function I want data like this
You have to set the value of each input field from the state that you set with changeHandler method. Additionally, you need to update the changeHandler method to update the state.allValues as follows.
(Following is the example code I used to test locally. Do the necessary modifications to fit it to your implementation)
import React, { Component } from "react";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
allValues: {
bloodsugar: "",
bloodpressure: "",
},
};
}
changeHandler = (e) => {
this.setState({
allValues: { ...this.state.allValues, [e.target.name]: e.target.value },
});
};
onsubmbit = (e) => {
e.preventDefault();
console.log(this.state.allValues);
};
render() {
return (
<form onSubmit={this.onsubmbit}>
<div>
<div style={{ fontSize: "4rem", padding: "15px" }}>
<i className="fa fa-level-up"></i>
</div>
<div style={{ padding: "10px" }}>
<strong>Enter your blood sugar level</strong>
<br />
<input
type="text"
name="bloodsugar"
onChange={this.changeHandler}
value={this.state.allValues.bloodsugar}
/>
</div>
</div>
<div>
<div style={{ fontSize: "4rem", padding: "15px" }}>
<i className="fa fa-area-chart"></i>
</div>
<div style={{ padding: "10px" }}>
<strong>Enter your blood pressure level</strong>
<br />
<input
type="text"
name="bloodpressure"
onChange={this.changeHandler}
value={this.state.allValues.bloodpressure}
/>
</div>
</div>
<button type="submit">Submit</button>
</form>
);
}
}
Related
I am trying to submit a file and text input to backend with POST request, the code looks like this,
state={
text:'',
file:''
}
handleTextChange = (e) => {
this.setState({[e.target.name]:e.target.value})
}
handleFileChange = (e) => {
this.setState({file:e.target.files[0]})
}
handleSubmit = (e) => {
const {text,file} = this.state
//POST request with text and file
}
But the file is always empty, If I console.log(e.target.files[0]), it shows a FileList in console but somehow it is not updated in state
I am quite new in react, your help is very much appreciated, thanks
EDIT: the form looks like this
<form action="" className="w-100" onSubmit={(e) => this.handleSubmit(e)}>
<div className="pt-1 pb-3">
<TextAreaAutosize
className="form-control"
placeholder="write some text here"
minRows="4"
name="text"
onChange={(e) => this.handleChange(e)}
/>
</div>
<div className="w-100 d-flex justify-content-between align-items-center">
<div>
<input
type="file"
className="form-control-file"
name="file"
onChange={(e) => this.handleFileChange(e)}
/>
</div>
<div>
<button type="submit" className="btn btn-primary">
Post
</button>
</div>
</div>
</form>
sandbox:
https://codesandbox.io/s/friendly-banzai-8ifw4?fontsize=14&hidenavigation=1&theme=dark
try this one works just fine
before install
run npm install #material-ui/core
import React, { Component } from 'react';
import './App.css';
import { TextareaAutosize } from '#material-ui/core';
class App extends Component {
constructor(props) {
super(props)
this.state = {
text: '',
file: ''
}
this.handleFileChange=this.handleFileChange.bind(this)
this.handleTextChange=this.handleTextChange.bind(this)
this.handleSubmit=this.handleSubmit.bind(this)
}
handleTextChange = (e) => {
this.setState({ [e.target.name]: e.target.value })
}
handleFileChange = (e) => {
console.log(e.target.files[0])
this.setState({ file: e.target.files[0] })
}
handleSubmit = (e) => {
const { text, file } = this.state
}
render() {
return (
<div className="App">
<form action="" className="w-100" onSubmit={(e) => this.handleSubmit(e)}>
<div className="pt-1 pb-3">
<TextareaAutosize
className="form-control"
placeholder="write some text here"
minRows="4"
name="text"
onChange={(e) => this.handleChange(e)}
/>
</div>
<div className="w-100 d-flex justify-content-between align-items-center">
<div>
<input
type="file"
className="form-control-file"
name="file"
onChange={(e) => this.handleFileChange(e)}
/>
</div>
<div>
<button type="submit" className="btn btn-primary">
Post
</button>
</div>
</div>
</form>
</div>
);
}
}
export default App;
More of a two part question: I need to define each of the onChange handle functions in my parent component and pass them to respective child components. After that How would I get the value of form elements in your parent component?
class App extends Component {
render() {
const handleChange = (data) =>
{console.log(data)}
return (
<div className="App">
<PageOne handleChange={handleChange} />
<PageTwo />
<PageThree />
<PageFour />
<PageFive />
<PageSix />
<Button onSubmit={this.props.handleChange()}>
Submit Form
</Button>
<br/>
<br/>
</div>
);
}
}
Page One Component
class PageOne extends Component {
constructor(props){
super(props)
this.state={
generalDetails: '',
phoneNumber: '',
fName: '',
mName: '',
lName: '',
gender: '',
}
this.handleInputChange = this.handleInputChange.bind(this);
}
handleChange = (data) =>
{console.log(data)
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked :
target.value;
const name = target.name;
console.log(`Input name ${name}. Input value ${value}.`);
this.setState({
[name]: value
});
}
render() {
return (
<div className="PageOneWrapper"
style={{
background: '#969fad'
}}
>
<div className="Details">
<h1>CareerTrackers Program Orientation</h1>
<p> Please complete this form to ensure we have your most up-to-date contact details. </p>
<Form>
<TextArea
onChange={this.handleInputChange}
name="generalDetails"
placeholder='General Details'
style={{
width: 500,
minHeight: 50
}}
/>
</Form>
<br/>
<p style={{
marginRight: 600
<Input
onChange={this.handleInputChange}
name='fName'
placeholder='First Name'
/>
<Input
onChange={this.handleInputChange}
name='mName'
placeholder='Middle Name'
style={{
marginLeft: 50,
marginRight: 50
}}
/>
<Input
onChange={this.handleInputChange}
name='lName'
placeholder='Last Name'
/>
<br/><br/><br/>
<p
style={{
display: "inline",
marginRight: 480
}}
><strong>Gender: </strong>
</p>
<select
name='gender'
onChange={this.handleInputChange}
style={{
display: "inline",
}}
>
<option>Select Gender </option>
<option>Male </option>
<option>Female </option>
<option>Other </option>
</select>
<br/><br/><br/>
<p style={{
marginRight: 600
}}><strong>Email:</strong></p>
<Input
onChange={this.handleInputChange}
name='email'
placeholder='Email'
style={{
marginRight: 470,
}}
/>
<br/>
<br/>
<Input
onChange={this.handleInputChange}
name='confirmEmail'
placeholder='Confirm Email'
style={{
marginRight: 470,
}}
/>
<br/>
<br/>
<p style={{
marginRight: 540
}}><strong>Phone Number:</strong></p>
<Input
onChange={this.handleInputChange}
name='phoneNumber'
placeholder='Phone Number'
style={{
marginRight:370,
}}
/>
<select
onChange={this.handleInputChange}
name='Mobile Type'
style={{
MarginRight: 5000
}}
>
<option>Mobile Type</option>
<option>Mobile</option>
<option>Work</option>
<option>Home</option>
</select>
<br/>
<br/>
<br/><br/><br/>
</div>
</div>
);
}
}
export default PageOne;
I've summarized what you want.
There are several pages for user inputs
These pages are child of parent
Submit button and submit function is defined in parent
You want to put all input data in many pages into the submit function
How can I do this?
If above is correct, and you've not considered about React-Redux,
I highly recommend to try it.
React Redux is the official React binding for Redux. It lets your React components read data from a Redux store, and dispatch actions to the store to update data.
It would help to handle your situation.
By using it, you can store your various data into Redux store - it is central data storage
Eg. you can save many inputs into Redux store in child component, and read values from Redux store in parent component.
Here is sample code that will help you:
APP.js
import React, { Component } from 'react';
import './App.css';
import PageOne from './PageOne';
class App extends Component {
constructor(props){
super(props)
this.state={
generalDetails: 'Initial Text',
}
this.onContentChange = this.onContentChange.bind(this);
this.onSubmitForm = this.onSubmitForm.bind(this);
}
render() {
return (
<div>
<h1>{this.state.generalDetails}</h1>
<PageOne handleChange={this.onContentChange} />
<button onSubmit={this.onSubmitForm}>
Submit Form
</button>
</div>
);
}
onSubmitForm(){
//Perform all Required Logic on Form Submit
}
onContentChange(data){
console.log('in onContentChange');
console.log(data);
this.setState({
...this.state,
generalDetails: data.generalDetails
});
console.log(this.state);
}
}
export default App;
PageOne.js
import React, { Component } from 'react';
class PageOne extends Component {
constructor(props){
super(props)
this.state={
generalDetails: ''
}
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;
console.log(`Input name ${name}. Input value ${value}.`);
this.setState({
...this.state,
[name]: value
});
if(this.props.handleChange){
this.props.handleChange(this.state);
}
}
render() {
return <div>
<textarea
onChange={this.handleInputChange}
name="generalDetails"
placeholder='General Details'
style={{
width: 500,
minHeight: 50
}}
/>
</div>
}
}
export default PageOne;
I have added only one field as this is just sample code. You can updated code based on your requirements.
How would I go about preventing someone from adding nothing my to do list?
AppTodo.JS
import React, { Component } from "react";
import PropTypes from "prop-types";
export class AddTodo extends Component {
state = {
title: ""
};
onSubmit = e => {
e.preventDefault();
if (this.state.addTodo === "") {
alert("??");
} else {
this.props.addTodo(this.state.title);
this.setState({ title: "" });
}
};
onChange = e => this.setState({ title: e.target.value });
render() {
return (
<form onSubmit={this.onSubmit} stlye={{ display: "flex" }}>
<input
type="text"
name="title"
style={{ flex: "10", padding: "5px" }}
placeholder="Add Things Todo..."
value={this.state.title}
onChange={this.onChange}
/>
<input
type="submit"
value="Submit"
className="btn"
style={{ flex: "1" }}
/>
</form>
);
}
}
// Prop Types
AddTodo.propTypes = {
addTodo: PropTypes.func.isRequired
};
export default AddTodo;
I am new to React, just doing it for fun and spent a few hours trying to make conditionals work within the onSumbit method and even in the render() method, but can't seem to make anything work.
Thanks ahead of time.
You do not have an addTodo variable in your state, but you do have a title variable.
Change this.state.addTodo === "" to this.state.title === "" and it will work as expected.
class AddTodo extends React.Component {
state = {
title: ""
};
onSubmit = e => {
e.preventDefault();
if (this.state.title === "") {
alert("??");
} else {
this.props.addTodo(this.state.title);
this.setState({ title: "" });
}
};
onChange = e => this.setState({ title: e.target.value });
render() {
return (
<form onSubmit={this.onSubmit} stlye={{ display: "flex" }}>
<input
type="text"
name="title"
style={{ flex: "10", padding: "5px" }}
placeholder="Add Things Todo..."
value={this.state.title}
onChange={this.onChange}
/>
<input
type="submit"
value="Submit"
className="btn"
style={{ flex: "1" }}
/>
</form>
);
}
}
ReactDOM.render(
<AddTodo addTodo={todo => console.log(`Added todo: ${todo}`)} />,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I have a form with two input elements - one for name (type="text") and one for age (type="number"). I manage the form state in the parent component. I have my handler methods and everything set up. The form state changes when user types. Also the input value property on the name field receives its value based on the current state, but the number field does not receive it while user types but on a second interaction with the page (a click somewhere else let's say)
Here is my Form component:
const Form = (props) => {
return (
<div className="col-md-4 form">
<form id="myForm">
<div className="form-group">
<label>Please, enter your name</label>
<input onChange={props.inputChanged} id="name" type="text" className="form-control" name="name"
placeholder="Name" value={props.data.name}/>
</div>
<div className="form-group">
<label>How old are you?</label>
<input onChange={props.inputChanged} id="age" type="number" className="form-control" name="age"
placeholder="Age" value={props.data.age}/>
</div>
</div>
And the parent class based component which owns the state:
class DbControls extends Component {
//INITIAL STATE
state = {
name: '',
age: '',
greeting: 'hello',
role: 'admin'
}
//HANDLE USER INPUT FOR NAME AND AGE
inputHandler = (e) => {
if (e.target.id === 'name') {
this.setState({name: e.target.value})
} else if (e.target.id === 'age') {
this.setState({age: e.target.value})
}
}
//HANDE USER PREFERENCES FOR GREETING AND ROLE
selectHandler = (e) => {
if (e.target.id === 'greet') {
this.setState({greeting: e.target.value})
} else if (e.target.id === 'role') {
this.setState({role: e.target.value})
}
}
render() {
return (
<div className="container-fluid">
<div className="row">
<Form data={this.state} inputChanged={this.inputHandler} selectChanged={this.selectHandler}/>
<div className="col-md-6 table">
<Table tableFor="Admins table"/>
<Table tableFor="Moderators table"/>
</div>
</div>
</div>
);
}
}
I am not sure if this is an actual problem but I was just curious what might be the reason for that behavior?
As per some of your comments i understand that the real issue you are facing is the the DOM value attribute is not in sync with the value property.
This is by design, there is a lot of talk about this issue and it mostly related to the confusion people do with:
jsx value attribute / property
DOM (devtools html) value attribute
These are not the same thing.
There is another thing to consider, related to passwords exploit.
You can read this issue for better understanding and more details.
Simplify how the inputs are setting state based upon the input's e.target.name and e.target.value. By design, the DOM number input value will only update when unfocused, but state is always up-to-date.
Here's a working example: https://codesandbox.io/s/qzl5knl4kj
formInputs.js
import React, { Fragment } from "react";
export default ({ age, handleChange, name }) => (
<Fragment>
<label>Please, enter your name: </label>
<br />
<input
onChange={handleChange}
type="text"
className="uk-input"
name="name"
placeholder="Name"
value={name}
style={{ width: 300, marginBottom: 10 }}
/>
<br />
<label>How old are you?</label>
<br />
<input
onChange={handleChange}
type="number"
className="uk-input"
name="age"
placeholder="Age"
value={age}
style={{ width: 300, marginBottom: 10 }}
/>
<br />
</Fragment>
);
index.js
import React, { Component } from "react";
import { render } from "react-dom";
import FormInputs from "./formInputs";
import "uikit/dist/css/uikit.min.css";
import "./styles.css";
class App extends Component {
state = {
name: "",
age: "",
greeting: "hello",
role: "admin"
};
handleChange = ({ target: { name, value } }) => this.setState({ [name]: value });
handleFormClear = () => this.setState({ age: "", name: "" });
handleSubmit = e => {
e.preventDefault();
const { age, name } = this.state;
if (!age || !name) return;
alert(`Name: ${name}, Age: ${age}`);
};
render = () => (
<form onSubmit={this.handleSubmit} style={{ textAlign: "center" }}>
<h1>Mixed Input Fields</h1>
<FormInputs {...this.state} handleChange={this.handleChange} />
<button
style={{ marginBottom: 20, marginRight: 10 }}
type="submit"
className="uk-button uk-button-primary"
>
Submit
</button>
<button
style={{ marginBottom: 20 }}
type="button"
className="uk-button uk-button-danger"
onClick={this.handleFormClear}
disabled={!this.state.name && !this.state.age}
>
Clear
</button>
<div>
<pre style={{ margin: "auto", width: 300 }}>
<code>
Name: {this.state.name}
<br />
Age: {this.state.age}
</code>
</pre>
</div>
</form>
);
}
render(<App />, document.getElementById("root"));
I have a basic login form, I have implemented the form validation using material UI.
The validation is visible even when there is a value in the text box.
code:
LoginComponent
import React from "react";
import TextField from "material-ui/TextField";
import RaisedButton from "material-ui/RaisedButton";
export class loginComponent extends React.Component {
constructor() {
super();
this.state = {
username: "",
usernameError: "",
password: "",
passwordError:""
};
};
onChange = e => {
this.setState({
[e.target.name]: e.target.value
});
};
validate = () => {
let isError = false;
const errors = {
usernameError: "",
passwordError: ""
};
if (this.state.username.trim.length === 0) {
isError = true;
errors.usernameError = "Username is required";
}
if (this.state.password.trim.length === 0) {
isError = true;
errors.passwordError = "password is required";
}
this.setState({
...this.state,
...errors
});
return isError;
}
onSubmit = e => {
e.preventDefault();
const error = this.validate();
if (!error) {
console.log(this.state);
}
};
render() {
return (
<div className="container">
<div id="loginbox" style={{ marginTop: 50 }} className="mainbox col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2">
<div className="panel panel-info">
<div className="panel-heading">
<div className="panel-title">Sign In</div>
</div>
<div style={{ paddingTop: 30 }} className="panel-body">
<form id="loginform" className="form-horizontal" role="form">
<div style={{ marginBottom: 25 }} className="input-group">
<span className="input-group-addon"><i className="glyphicon glyphicon-user"></i></span>
<TextField
name="username"
floatingLabelText="User name"
value={this.state.username}
onChange={e => this.onChange(e)}
errorText={this.state.usernameError}
floatingLabelFixed
/>
</div>
<div style={{ marginBottom: 25 }} className="input-group">
<span className="input-group-addon"><i className="glyphicon glyphicon-lock"></i></span>
<TextField type="password"
name="password"
value={this.state.password}
floatingLabelText="password"
onChange={e => this.onChange(e)}
errorText={this.state.passwordError}
floatingLabelFixed
/>
</div>
<div style={{ paddingTop: 10 }} className="form-group">
<div className="col-sm-12 controls">
<RaisedButton label="Login" onClick={e => this.onSubmit(e)} primary />
</div>
</div>
</form>
</div>
</div>
</div>
</div>
);
}
}
This are basic required length validation that is still getting fired even after entering the values in text box, can someone suggest what i did wrong.
I think with your comparison:
this.state.password.trim.length will always return 0 as it calculating length of password.trim.
Use this.state.password.trim().length which will trim passowrd value and return its length.