How to submit the same form multiple times in React - javascript

I have a react app that requires the same form(s) to be submitted multiple times.
Below is my code for the control panel class.
The values are entered into separate forms, and the button is pressed, sending the form input field values to another component for processing. After this is done, I would like to be able to re-submit the form (eg: simply click the button again) and for the processing to start over.
The formSubmit field (in this.state) is set to false initially, but set to true when the form is submitted. Once this is done, the {this.state.formSubmit && } line (near the end) ensures that the processing starts when the formSubmit value is set to true. Once the processing is done, I assume that simply setting the formSubmit value to false again will allow for the form to be submitted again, but I do not yet know how to do this.
class App extends React.Component {
constructor(props) {
super(props);
this.state = { BO_course: "",
BO_max_speed: "",
formSubmit: false
};
this.handleInput = this.handleInput.bind(this);
this.handleFormSubmit = this.handleFormSubmit.bind(this);
}
handleInput (event) {
const value = event.target.value;
console.log(value);
this.setState({
...this.state,
[event.target.name]: value,
});
}
handleFormSubmit (event) {
console.log("Submitting form");
event.preventDefault();
this.setState({formSubmit: true});
// this.setState({formSubmit: false})
}
render () {
return (
<div className="App">
<div className="container">
<form onSubmit={this.handleFormSubmit}>
<label className="name">
Name
<input className="inputstyleright"
type="text"
name="nameinput"
onChange={this.handleInput}
/>
</label>
</form>
<form onSubmit={this.handleFormSubmit}>
<label className="surname">
Surname
<input className="inputstyleright"
type="text"
name="surnameinput"
onChange={this.handleInput}
/>
</label>
<input className="submitbutton" type="submit" value="Submit"/>
</form>
<div className="topleft">Control Panel</div>
<div className="square"></div>
</div>
{/* only evaluates to true if the form has been submitted */}
{this.state.formSubmit && <RM search1={this.state} />}
</div>
);
}
}
export default App;

I managed to solve it by updating the button to use an onClick function:
<input className="submitbutton" type="submit" value="Submit" onClick={()=>getRM(this.state)}/>
and changing
{this.state.formSubmit && <RM search1={this.state} />}
to just
{<RM />}
I also moved the function I was calling in the
<RM search1={this.state} />
part outside of the RM class itself. The function is now called by the onClick in the button eg: "getRM()"

Related

LifeCycle of onChange in react

I am writing a simple react application, now I am working on an element that can take the user's input. I have been very curious about the order of the execution of line of code inside the onChange() function. So I added a little print statement to see how exactly things are changed.
Here's my code
function CreateReview() {
const [input, setInput] = useState({
title:'',
content:''
})
useEffect(() => {
console.log('render');
},[input])
function handleChange(event){
const {name, value} =event.target;
console.log(1)
setInput(prevInput=>
{
console.log(2)
return{
...prevInput, //...prevInput is to reserve the last Input
[name]: value //name is dynamic, "title" then setTitle, "content" then setContent.
}
}
)
console.log(3)
console.log(event.target);
}
function handleClick(event){
event.preventDefault();
console.log(input);
}
return <div className = "container">
<h1>Create Review</h1>
<form>
<div className="form-group">
<input onChange={handleChange} name="title" value={input.title} autoComplete="off" className = 'form-control' placeholder="Your Name"></input>
</div>
<div className="form-group">
<textarea onChange={handleChange} name="content" value={input.content} autoComplete="off" className = 'form-control' placeholder="Review Content"></textarea>
</div>
<button onClick={handleClick} className="btn btn-large btn-info">Add Note</button>
</form>
</div>
}
export default CreateReview;
And here's the output console
Console screenshot
I wonder why it goes 1,3,2. is there any reason behind it?
Kindly go to react document to read more about how state works in react.
As far as your concerned useState or setState are the async events, so whenever you are try to call them it will execute later rather do synchronously(line by line).

React: generating input field data with a button component

I'm creating an intake form where a piece of data can be input into the text field, or generated randomly with a button next to the field.
I want to do this for 3 fields on the form so I created a component
called <RandomDataButton />
I'm stuck with how to make sure the results of the calculation done by the button component update the value of the text box so that the form submission contains the generated data.
I don't fully understand the state propagation, but what I do understand is that the flow is one way, down the hierarchy of components.
So what I am attempting to do is have a choice of inputting some data in the text box, or generating some random data from a button (I'd like to reuse it in other ui creations)
Where I am stuck is how do I update the input field from the componenet that is lower in the hierarchy.
Do I pass the state to the randomizer button and then have it update a copy of state? Or am I totally off base with that approach?
App:
class App extends React.Component {
render(){
return (
<div>
<DataInputForm />
</div>
);
}
}
DataInputForm:
class DataInputForm extends React.Component{
state= {
projectname: '',
datasource: '',
data1: '',
data2: '',
data3: '',
};
handleSubmit = e => {
e.preventDefault();
console.log({
projectname: this.projectname.value,
datasource: this.datasource.value,
data1: this.data1.value,
data2: this.data2.value,
data3: this.data3.value,
});
}
handleChange = e => this.setState({[e.target.name]: e.target.value});
render(){
return(
<form className="ui form" onSubmit={this.handleSubmit}>
<div className="field">
<label htmlFor="projectname">Project Name: </label>
<input
type="text"
id="projectname"
name="projectname"
placeholder="Project Name"
ref={input => this.projectname = input}
/>
</div>
<div className="field">
<label htmlFor="datasource">Data Source: </label>
<input
type="text"
id="datrasource"
name="datasource"
placeholder="Data Source"
ref={input => this.datasource = input}
/>
</div>
<div className="field">
<label htmlFor="data1">Data 1: </label>
<input
type="number"
min="3"
max="18"
id="data1"
name="data1"
ref={input => this.data1 = input}
/>
<RandomDataButton buttonid={"data1button"} buttonname={"Data1"} />
</div>
<div className="field">
<label htmlFor="data2">Data 2: </label>
<input
type="number"
min="3"
max="18"
id="data2"
name="data2"
ref={input => this.data2 = input}
/>
<RandomDataButton buttonid={"data2button"} buttonname={"Data2"} />
</div>
<div className="field">
<label htmlFor="data3">Data 3: </label>
<input
type="number"
min="3"
max="18"
id="data3"
name="data3"
ref={input => this.data3 = input}
/>
<RandomDataButton buttonid={"data3button"} buttonname={"Data3"} />
</div>
<button className="ui button" type="submit">Create Data</button>
</form>
);
}
}
RandomDataButton:
const getRandom = max => Math.floor(Math.random() * Math.floor(max));
class RandomDataButton extends React.Component {
generateData(value){
var result, destination;
destination = value.toLowerCase();
result = getRandom(1000);
console.log("Generated " + result + " for range of " + value + "]: " + destination);
//this.state.{destination};
}
render(){
return(
<button id={this.props.buttonid} type="button" onClick={this.generateData.bind(null,this.props.buttonname)}>{this.props.buttonname}</button>
//<button id="strbutton" type="button">Generate</button>
);
}
}
Pass a function as prop to RandomDataButton. Define the function in DataInputForm and use it update the state in DataInputForm by calling the prop function from RandomDataButton whenever you need the update.
It seems you are working with multiple components, so while working with multiple components, it is highly recommended to use any central storage container, which would be useful to get your desired data in any components
Flux and redux both are tested architectures for data state management, you could use any of them, I would recommend using redux.
Here's a codesandbox for your reference: https://codesandbox.io/s/bold-frog-01ff2
This is effectively a continuation of Amala's suggestion.
You are correct, the hierarchy is one-way. Which means we should define a function in DataInputForm (lvl2) and pass it as a prop to RandomDataButton (lvl3). That function is bound to DataInputForm's execution context, and we want to update it's state so we can feed the new data back into each individual input.
For example:
createRandomText = (associatedField, value) => {
this.setState(
{
[associatedField]: value
},
() => console.log(this.state)
);
};
So to update the state correctly, we need to provide a field corresponding to the right input, and a value (the randomized value).
We pass in that function as a prop to RandomDataButton and use it for the onClick() handler.
class RandomDataButton extends React.Component {
generateData = () => {
let result = getRandom(1000);
this.props.createRandomText(this.props.matchingInput, result);
};
render() {
return (
<button
id={this.props.buttonid}
type="button"
onClick={this.generateData}
>
{this.props.buttonname}
</button>
//<button id="strbutton" type="button">Generate</button>
);
}
}
Additionally we need to provide another prop to the button component so we can call the above function correctly:
<RandomDataButton
buttonid={"data1button"}
buttonname={"Data1"}
createRandomText={this.createRandomText}
matchingInput={"data1"}
/>
See sandbox for full details :)

Text Input should not lose focus if validation fails in ReactJS

In NewFormComponent, I have onBlur on first input which is checking if fname is "" then console "Validation failed"
Requirement: Textfield should not lose focus until the user enters some value or it should pass Validations. In other words, until the validation is passed user can't select or tab to other text fields in the same form.
I have tried using ref and calling focus() method, but it textfield to gain focus but user is still able to select other textfields.
import React, { Component } from 'react'
export default class NewFormComponent extends Component {
constructor(props) {
super(props)
this.state = {
fname:"",
lname:""
}
this.handleChange = this.handleChange.bind(this);
this.onFormSubmit = this.onFormSubmit.bind(this);
}
handleChange(e){
this.setState({
[e.target.name]:e.target.value
})
}
onFormSubmit(e){
e.preventDefault();
console.log(`Hi ${this.state.fname} ${this.state.lname}`)
}
render() {
return (
<div>
<form onSubmit={this.onFormSubmit}>
<input type="text"
name="fname"
value={this.state.fname}
onChange={this.handleChange}
onBlur={()=>{
if(this.state.fname === ""){
console.log("Validation failed");
}
}}
/>
<input type="text"
name="lname"
value={this.state.lname}
onChange={this.handleChange}/>
<input type="submit" value="submit"/>
</form>
</div>
)
}
}
Expection: Textfield shouldn't lose focus until validation is passed

Getting value of input in React and checking it

I have an input field and a button. I want to make so that if a user enters a value in the input field that is a number when he clicks the button a div with information should appear. Right now when the button is clicked it loads my data, but it works even if the input is empty. How can I properly get the value from the input, check if its a number and if it is indeed a number the div should display the info, here is what I made so far:
class CardCheck extends Component {
constructor(props) {
super(props);
this.state = { showMessage: false };
}
_checkValue() {
if (evt.taget.value != number) {
this.setState(prevState => ({
showMessage: !prevState.showMessage
}));
} else {
alert("Your card id can consist only of numbers!")
}
}
_showMessage = () =>
this.setState(prevState => ({
showMessage: !prevState.showMessage
}));
render() {
return (
<div>
<div className="newsletter-container">
<h1>Enter the ID of your card:</h1>
<div className="center">
<input type="number" onChange={(evt) => { console.log(evt.target.value)}} />
<input type="submit" value="Check" onClick={this._showMessage {this._checkValue} />
</div>
<div />
{this.state.showMessage && (
<div className="results">
<h2 className="green-heading">Your card is valid in the following places:</h2>
<p>Magic Auto Spa</p>
<p>Ivans auto shop</p>
<p>AutoHouse Sofia</p>
<p>Bankya Auto Palace</p>
<button className="close" onClick={this._showMessage}>
Close
</button>
</div>
)}
</div>
<h1>Offers:</h1>
</div>
);
}
}
export default CardCheck;
I tried obtaining the value with the onChange event, check it's type with an if statement and attach that event as a second onClick but it does not work
You have a typo in your code:
_checkValue() {
if (evt.taget.value != number) {
// -------^ should be target
Also, Number.isNaN would be a more robust comparison.
First, you have an error in
<input type="submit" value="Check" onClick={this._showMessage{this._checkValue} />
Next,
<input> Boxes in React works a little bit differently.
Check out this link

Checkbox in react js doesn't change

I have main component as follows :
export default class RegistrationFormStepFour extends React.Component{
constructor(props){
super(props);
this.state = {
terms: false,
emailNotifications: false,
smsNotifications: false,
errors: {}
}
}
handleTerms(event){
event.preventDefault();
this.setState({terms: !this.state.terms});
}
render(){
const language = this.props.currentLanguage;
return (
<div>
<Terms
nameYes="chcTerms"
text={language.termsText}
state={this.state.terms}
onChange={this.handleTerms.bind(this)}
currentLanguage={language}
error={this.state.errors.terms}/>
</div>
);
}
}
And component term is as follows :
import React from 'react';
const Terms = ({nameYes, text, state, onChange, error}) => {
let hasError = error ? "hasError" : "";
return (
<div className="col-lg-12 text-center" style={{marginBottom: 30}}>
<form>
<label className="radio-inline">
<input
type="checkbox"
name={nameYes}
checked={state}
onChange={onChange}
value=""/>
</label>
</form>
<p className={`questionsText ${hasError}`} style={{marginTop: 10}}>{text}</p>
</div>
);
};
export default Terms;
But when I click on the checkbox, nothing happens. If I console log the state in the terms component it show right value. First time is false, when I click on the checkbox than is true, but the checkbox isn't checked.
Any advice?
The event.preventDefault() is causing your problems in the controlled component checkbox.
http://www.matthiaslienau.de/blog/tags/checkbox
Checkboxes (and Radio Buttons): Manually updating state fails for checkboxes (and without having tested it: I think for radio controls as well). Why? The problem one will face is that the checkbox onChange event behaves in a special way since the era of HTML (how could I forget!): You may not toggle the state of a checkbox manually via the .checked property. Nor does React. The onChange (onClick) event is fired after the element state changed internally. This may just be reverted based on the return value of the event handler. See this post for a comprehensive examination of this fact.
const Terms = ({ nameYes, text, state, onChange, error }) => {
let hasError = error ? "hasError" : "";
return (
<div>
<form>
<label className="radio-inline">
<input
type="checkbox"
name={nameYes}
checked={state}
onChange={onChange}
/>
</label>
</form>
<p className={`questionsText ${hasError}`}>{text}</p>
</div>
);
};
class RegistrationFormStepFour extends React.Component {
constructor(props) {
super(props);
this.state = {
terms: false,
emailNotifications: false,
smsNotifications: false,
errors: {}
}
}
handleTerms(event) {
this.setState({ terms: event.target.checked });
}
render() {
const language = { termsText: 'Some Language' };
return (
<div>
<Terms
nameYes="chcTerms"
text={language.termsText}
state={this.state.terms}
onChange={this.handleTerms.bind(this)}
currentLanguage={language}
error={this.state.errors.terms}/>
{JSON.stringify(this.state)}
</div>
);
}
}
ReactDOM.render(<RegistrationFormStepFour />, 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"></div>
I think you should remove value attr from input tag. try this :
<input
type="checkbox"
name={nameYes}
checked={state}
onChange={onChange}
/>

Categories

Resources