I'm trying to follow the Handling Multiple Inputs example from:
https://facebook.github.io/react/docs/forms.html#handling-multiple-inputs
I tried to add two form elements, firstName and lastName. One is rendered within the main render() function, whereas the other is created using a separate JSX function called LastName().
The result is available here:
https://codepen.io/sagiba/pen/Kmdrdz?editors=0010
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2,
firstName: 'John',
lastName: 'Doe'
};
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
});
}
render() {
const LastName = () => {
return (
<label>
Last Name:
<input
name="lastName"
type="text"
value={this.state.lastName}
onChange={this.handleInputChange} />
</label>
);
};
return (
<form>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
<br />
<label>
First Name:
<input
name="firstName"
type="text"
value={this.state.firstName}
onChange={this.handleInputChange} />
</label>
<br />
<LastName />
</form>
);
}
}
ReactDOM.render(
<Reservation />,
document.getElementById('root')
);
<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>
Both are rendered as expected. However when trying to edit the value of last name the component is losing focus on every keystroke. This doesn't happen with firstName.
What am I doing wrong?
React will rerender the application each time there is a change in state. Because of this, it runs the function to recreate your last name component; the function returns something "new" everytime. Just remove it from the function and you'll be golden.
render() {
return (
<form>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
<br />
<label>
First Name:
<input
name="firstName"
type="text"
value={this.state.firstName}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Last Name:
<input
name="lastName"
type="text"
value={this.state.lastName}
onChange={this.handleInputChange} />
</label>
</form>
);
}
}
Related
I am importing a form written in GoogleApps Script into an iframe on a page built with Squarespace but for the life of me cannot prevent the form from submitting. I am using:
window.addEventListener( 'load', preventFormSubmit );
as suggested in GAS documentation but this does not seem to be triggering the preventFormSubmit function. Instead, when the submit button is clicked the form submits and goes to a blank google page. Also the alerts in the preventFormSubmit function (now commented out) never display which suggests that the form is never called.
I have spent days on this, cannot find an answer anywhere and can no longer see the woods for the trees. Any clues as to what I am doing wrong?
Squarespace is a website builder which enables one to embed code, in this case as an iframe.
My code:
js.html:
<script>
function preventFormSubmit() {
//alert( "prevent form submit triggered" );
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(event) {
event.preventDefault();
});
}
//alert( "forms prevented from submitting: " = forms.length );
}
window.addEventListener( "ready", preventFormSubmit );
function handleFormSubmit(formObject) {
google.script.run
.withSuccessHandler( showSuccess )
.withFailureHandler( showError )
.processForm_1( formObject );
}
</script>
html:
<!DOCTYPE html >
<head>
<base target="_top" >
<?!= include('css'); ?>
<?!= include('js'); ?>
</head>
<body>
<div id="formDiv" class="card" >
<h2 id="title" >Alternative Booking form</h2>
<form id="alternative-booking-form-1" onsubmit="handleFormSubmit(this)" >
<fieldset>
<legend>About You</legend>
<p>Please tell us a bit about yourself.
</p>
<input type="text" id="firstName" name="firstName" form="alternative-booking-form-1"
placeholder="your first name" value="" required
/><br />
<input type="text" id="lastName" name="lastName" form="alternative-booking-form-1"
placeholder="your last name" value="" required
/><br />
<input type="text" id="title" name="title" form="alternative-booking-form-1"
placeholder="your title, eg: mr, mrs, ms etc" value="" /><br>
</fieldset>
<fieldset>
<legend>Your Contact Details</legend>
<p>We will only use your contact details in case we need to contact you with regard to
this booking, unless you consent
to further communications, as offered later in this booking process.</p>
<input type="email" id="email" name="email" form="alternative-booking-form-1"
placeholder="your email address" value=""
required /><br />
<input type="tel" id="phone" name="phone" form="alternative-booking-form-1"
placeholder="phone" value="" required /><br />
</fieldset>
<fieldset>
<input type="hidden" id="form" name="form" form="alternative-booking-form-1" value="1" />
<br />
<input type="submit" id="submit" name="submit" form="alternative-booking-form-1"
class="red" value="Next →" />
<br />
<br />
</fieldset>
</form>
</div>
<div id="output" name="output" ></div>
</body>
<!DOCTYPE html >
<head>
<base target="_top" >
<?!= include('css'); ?>
<?!= include('js'); ?>
</head>
<body>
<div id="formDiv" class="card" >
<h2 id="title" >Alternative Booking form</h2>
<form id="alternative-booking-form-1" >
<fieldset>
<legend>About You</legend>
<p>Please tell us a bit about yourself.
</p>
<input type="text" id="firstName" name="firstName" form="alternative-booking-form-1"
placeholder="your first name" value="" required
/><br />
<input type="text" id="lastName" name="lastName" form="alternative-booking-form-1"
placeholder="your last name" value="" required
/><br />
<input type="text" id="title" name="title" form="alternative-booking-form-1"
placeholder="your title, eg: mr, mrs, ms etc" value="" /><br>
</fieldset>
<fieldset>
<legend>Your Contact Details</legend>
<p>We will only use your contact details in case we need to contact you with regard to
this booking, unless you consent
to further communications, as offered later in this booking process.</p>
<input type="email" id="email" name="email" form="alternative-booking-form-1"
placeholder="your email address" value=""
required /><br />
<input type="tel" id="phone" name="phone" form="alternative-booking-form-1"
placeholder="phone" value="" required /><br />
</fieldset>
<fieldset>
<input type="hidden" id="form" name="form" form="alternative-booking-form-1" value="1" />
<br />
<input type="button" id="submit" name="submit" form="alternative-booking-form-1"
class="red" value="Next →" />
<br />
<br />
</fieldset>
</form>
</div>
<div id="output" name="output" ></div>
<script>
window.onload = function() {
document.getElementById("alternative-booking-form-1").addEventListener( "ready", handleFormSubmit );
}
function handleFormSubmit(formObject) {
google.script.run
.withSuccessHandler( showSuccess )
.withFailureHandler( showError )
.processForm_1( formObject );
}
</script>
</body>
I want to extract in my Controller.java this way (#PathVariable Integer id):-
// Get /http://localhost:9091/getFeedback/138
#GetMapping("/getFeedback/{id}")
public Feedback getFeedback(#PathVariable Integer id) {
return service.getFeedback(id);
}
Not this way:-
#GetMapping("/getFeedback")
public Feedback getFeedback(#RequestParam Integer id) {
return service.getFeedback(id);
}
I tried :
<form method="Get" action="getFeedback/">
ID: <input type="text" name="name" id="name" /><br />
<input type="submit" value="Submit" />
</form>
You can use onsubmit:
<form
method="Get"
action="getFeedback/"
onsubmit="this.action = this.action + this.name.value; this.submit();"
>
ID: <input type="text" name="name" id="name" /><br />
<input type="submit" value="Submit" />
</form>
I am trying to set up a form tracking with Woopra on my WordPress website but it does not work.
Below my HTML form :
<form id="subForm" class="af-form-wrapper wpcf7-form" action="http://campaign.clever-age.com/t/r/s/kuuhpd/" method="post" data-mautic-form="conferencemonitoringecp16">
<input id="fielddrhhqlu" class="text" name="cm-f-drhhqlu" required="" type="text" placeholder="Nom ( obligatoire )" />
<input id="fielddrhhqo" name="cm-f-drhhqo" required="" type="text" placeholder="Prenom (obligatoire)" />
<input id="fielddrhhqn" name="cm-f-drhhqn" required="" type="text" placeholder="Société (obligatoire)" />
<input id="fielddrhhqb" name="cm-f-drhhqb" required="" type="tel" placeholder="Téléphone (obligatoire)" />
<input id="fieldEmail" name="cm-kuuhpd-kuuhpd" required="" type="email" placeholder="Adresse E-mail (obligatoire)" />
<button id="mauticform_input_magento114form_submit" name="mauticform[submit]" type="submit">Recevoir le guide </button>
</form>
I would like to track name, company and email data only. Below my JS script :
<script>
woopra.call('trackForm', 'Magento2', 'subForm', {
identify: function(form) {
return {
Name: form.cm-f-drhhqlu,
Company: form.cm-f-drhhqn,
Email: form.cm-kuuhpd-kuuhpd
};
},
});
</script>
Any help is greatly appreciated ! :-)
Below my solution.
HTML :
<form id="subForm" class="af-form-wrapper wpcf7-form" action="http://campaign.clever-age.com/t/r/s/kuuhpd/" method="post" data-mautic-form="conferencemonitoringecp16" onsubmit="identify()">
<input id="fielddrhhqlu" class="text" name="cm-f-drhhqlu" required="" type="text" placeholder="Nom ( obligatoire )" />
<input id="fielddrhhqo" name="cm-f-drhhqo" required="" type="text" placeholder="Prenom (obligatoire)" />
<input id="fielddrhhqn" name="cm-f-drhhqn" required="" type="text" placeholder="Société (obligatoire)" />
<input id="fielddrhhqb" name="cm-f-drhhqb" required="" type="tel" placeholder="Téléphone (obligatoire)" />
<input id="fieldEmail" name="cm-kuuhpd-kuuhpd" required="" type="email" placeholder="Adresse E-mail (obligatoire)" />
<button id="mauticform_input_magento114form_submit" name="mauticform[submit]" type="button" onclick="identify();">Recevoir le guide </button>
</form>
JS :
<script type="text/javascript"><!--
$(function() {
woopra.call('trackForm', 'Magento', '#subForm', {
});
});
function identify() {
var emailField = document.getElementById('fieldEmail').value;
var nameField = document.getElementById('fielddrhhqo').value + " " + document.getElementById('fielddrhhqlu').value;
var companyField = document.getElementById('fielddrhhqn').value;
woopra.identify({
email: emailField,
name: nameField,
company: companyField
}).push(submitForm);
}
function submitForm() {
var form = document.getElementById("subForm");
form.submit();
}
--></script>
Hope it helps if someone is facing the same issue.
Not sure why the setState function in the addUser() not doing it's job. The POST request works fine, but the inputs don't clear and that is an issue for the users. Perhaps a second pair of eyes, can spot the flaw.
import React, { Component, PropTypes } from 'react';
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
import { Link } from 'react-router';
// Import Style
import styles from './UserRegistrationForm.css';
export class UserRegistrationForm extends Component {
constructor(props) {
super(props);
this.state = { nickname: '', studentId: '', email: '', password: '' };
this.handleInputChange = this.handleInputChange.bind(this);
this.addUser = this.addUser.bind(this);
}
handleInputChange(event) {
this.setState({
[event.target.name]: event.target.value,
});
}
addUser = () => {
if (this.state.nickname && this.state.studentId && this.state.email && this.state.password) {
this.props.addUser(this.state.nickname, this.state.studentId, this.state.email, this.state.password);
this.setState({ nickname: '', studentId: '', email: '', password: '' });
}
};
render() {
return (
<div className={`${styles.formContainer} ${styles.center}`}>
<i className={`${styles.cap} fa fa-graduation-cap`} />
<h1 className={styles.title}><FormattedMessage id="siteTitle" /></h1>
<div className="row">
<form method="POST" className="col-lg-4 push-lg-4 col-md-6 push-md-3 col-xs-8 push-xs-2">
<div className="form-group row">
<label className="input-labels">Full Name</label>
<input type="text" className="form-control" name="nickname" placeholder="Full Name" onChange={this.handleInputChange} />
</div>
<div className="form-group row">
<label className="input-labels">Student ID</label>
<input type="text" className="form-control" name="studentId" placeholder="Student ID" onChange={this.handleInputChange} />
</div>
<div className="form-group row">
<label className="input-labels">Email</label>
<input type="email" className="form-control" name="email" placeholder="Email" onChange={this.handleInputChange} />
</div>
<div className="form-group row">
<label className="input-labels">Password</label>
<input type="password" className="form-control" name="password" placeholder="Password" onChange={this.handleInputChange} />
</div>
<div className={styles.center}>
<button
className={`${styles.btnOutlineSecondary} btn btn-outline-secondary ${styles.signInButton}`}
type="button" onClick={this.addUser}
>
Register and Start Studying!
</button><br /><br />
<Link to="/profile"><button className="btn btn-info" type="button">Temp Button to Profile Page</button></Link><br /><br />
<Link to="/">Already have an account? Sign in Here</Link>
</div>
</form>
</div>
</div>
);
}
}
UserRegistrationForm.propTypes = {
addUser: PropTypes.func.isRequired,
intl: intlShape.isRequired,
};
export default injectIntl(UserRegistrationForm);
There is no two-way data-binding in react, so you have to be careful when implementing controlled components https://facebook.github.io/react/docs/forms.html#controlled-components
for every one of your inputs, to make them controlled inputs, that will clear on submit, you must set their values to the corresponding state value, e.g.
<input value={this.state.nickname} type="text" className="form-control" name="nickname" placeholder="Full Name" onChange={this.handleInputChange} />
and
<input value={this.state.nickname} type="text" className="form-control" name="studentId" placeholder="Student ID" onChange={this.handleInputChange} />
... for every one of your inputs, adding the value attribute will make sure they stay in sync with, this.setState calls
I cannot find an answer to this specific situation on Stack Overflow, I do not think this is a duplicate.
I have a form component built in React that looks like this:
"use strict";
import React from "react";
import GameActions from "./../../actions/games";
import lodash from "lodash";
export default class GamesForm extends React.Component {
constructor(props) {
super(props);
this.state = this._getInitialState();
this._getInitialState = this._getInitialState.bind(this);
this._onChange = this._onChange.bind(this);
this._onSubmit = this._onSubmit.bind(this);
}
componentWillUnmount() {
console.log("unmounted");
}
componentDidMount() {
console.log("mounted");
}
_getInitialState() {
return {
game: {
homeTeam: "",
homeTeamScore: 0,
visitingTeam: "",
visitingTeamScore: 0,
date: new Date(),
parkName: "",
city: "",
state: "",
tournament: "",
sanction: ""
}
};
}
_onChange(e) {
e.preventDefault();
var newState = lodash.cloneDeep(this.state);
newState.game[e.target.name] = e.target.value;
this.setState(newState);
}
_onSubmit(e) {
e.preventDefault();
GameActions.create(this.state);
this.setState(this._getInitialState);
}
render() {
return (
<form onSubmit={this._onSubmit}>
<div className="form-group">
<div className="row">
<div className="col-xs-10">
<label for="homeTeam">Home Team</label>
<input name="homeTeam" className="form-control input-md" value={this.state.game.homeTeam} onChange={this._onChange} autofocus={true} />
</div>
<div className="col-xs-2">
<label for="homeTeamScore">Score</label>
<input name="homeTeamScore" className="form-control input-md" value={this.state.game.homeTeamScore} onChange={this._onChange} />
</div>
</div>
</div>
<div className="form-group">
<div className="row">
<div className="col-xs-10">
<label for="visitingTeam">Visiting Team</label>
<input name="visitingTeam" className="form-control input-md" value={this.state.game.visitingTeam} onChange={this._onChange} />
</div>
<div className="col-xs-2">
<label for="visitingTeamScore">Score</label>
<input name="visitingTeamScore" className="form-control input-md" value={this.state.game.visitingTeamScore} onChange={this._onChange} />
</div>
</div>
</div>
<hr />
<div className="form-group">
<div className="row">
<div className="col-xs-12">
<label for="date">Date</label>
<input name="date" className="form-control input-md" placeholder="03/27/2016" value={this.state.game.date} onChange={this._onChange} />
</div>
</div>
</div>
<hr />
<div className="form-group">
<div className="row">
<div className="col-xs-12">
<label for="parkName">Park Name</label>
<input name="parkName" className="form-control input-md" placeholder="ex. Riverview Park, Patriots Park" value={this.state.game.parkName} onChange={this._onChange} />
</div>
<div className="col-xs-6">
<label for="parkCity">City</label>
<input name="parkCity" className="form-control input-md" value={this.state.game.parkCity} onChange={this._onChange} />
</div>
<div className="col-xs-6">
<label for="parkState">State</label>
<select name="parkState" className="form-control input-md" defaultValue="0" value={this.state.game.parkState} onChange={this._onChange}>
<option value="0" disabled>Select one</option>
<option value="AK">Alaska</option>
</select>
</div>
</div>
</div>
<hr />
<div className="form-group">
<div className="row">
<div className="col-xs-8">
<label for="tournamentName">Tournament Name</label>
<input name="tournamentName" className="form-control input-md" placeholder="ex. Winter Bump" value={this.state.game.tournamentName} onChange={this._onChange} />
</div>
<div className="col-xs-4">
<label for="tournamentSanction">Sanction</label>
<input name="tournamentSanction" className="form-control input-md" placeholder="ex. USSSA" value={this.state.game.tournamentSanction} onChange={this._onChange} />
</div>
</div>
</div>
<hr />
<div className="form-group">
<button type="submit" className="btn btn-lg btn-success btn-block">Submit</button>
</div>
</form>
);
}
}
I have two different views, one that houses the form and one that houses the list. When starting on the form page, the _onSubmit function works properly without warnings. After that, I navigate to the list page, then back to the form page and try to submit the form again. Now it fires the warning:
Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the undefined component.
Furthermore, the unmounted and mounted are logged in the console at the right time.
I am using React Router so that may be factoring into the issue.
Edit: I should also add that setState works both times, it just throws a warning the second time.
Edit: If you take out the GameActions.create(this.state) line, it does not throw a warning.
Why am I getting the error only when I navigate back to the form and not the first time? How can I fix it?
React Router Routes
<Router history={hashHistory}>
<Route path="/" component={Navbar}>
<IndexRoute component={IndexPage} />
<Route path="games" component={GamesIndexPage} />
<Route path="games/create" component={GamesCreatePage} />
</Route>
</Router>
Actions
export default class GameActions {
static create(game) {
Dispatcher.dispatch({
actionType: GameConstants.CREATE,
game: game
});
}
}
GamesCreatePage
"use strict";
import React from "react";
import GamesForm from "./../../components/games/form.jsx";
export default class GamesCreatePage extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<GamesForm />
);
}
}
As an advice: try to change the component state inside the componentWillMount() instead of constructor.
And one more point avoid using this.state = {} use this.setState({}).
Maybe this is not a direct answer to your question but change this stuff and try again, maybe you will get more proper result.
Please comment after the suggested changes and I will try to help if some points will remain.