What is the proper way to clear a React Form? - javascript

I have a form that has a few different type of elements (textbox, checkbox, etc.) that was created using Reactjs. I have been having a hard time trying to figure out how to clear a form. I've googled and not really sure of those solutions. I tried something like the following but found it was of no use.
What I want to happen is if the user fills out the form and decides to clear the form, once they click 'Clear Form', the form should reset. All the fields need to be blank again.
handleClearForm(){
this.setState({
decisionDate: '',
Veggies:'',
fullName:'',
comment:''
})
}
How can I clear a form in react? Any help would be much appreciated.
Code

Check this improved code
class App extends React.Component{
constructor(){
super()
this.state = {
decisionDate: '',
Veggies:'',
fullName:'',
comment:''
}
}
setdecisionDateValue (value) {
this.setState({
decisionDate: value
})
}
componentDidMount(){
$( "#decisionDate" ).datepicker({
onSelect: this.setdecisionDateValue
});
}
handleClearForm = () => {
this.setState({
decisionDate: '',
Veggies:'',
fullName:'',
comment:''
})
}
handleChange = (e) => {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({[name]: value})
}
render(){
const { decisionDate,Veggies,fullName,comment} = this.state;
return(
<div>
<input type="text" name="fullName"
placeholder="Full Name"
onChange={this.handleChange}
value={fullName}/><br /><br />
<input type="text"
name="decisionDate"
id="decisionDate"
onChange={this.handleChange}
placeholder="MM/DD/YYYY"
value={this.state.decisionDate} /><br /><br />
<textarea name="comment"
value={comment}
onChange={this.handleChange}/><br /><br />
<input
type="checkbox"
name="Veggies"
onChange={this.handleChange}
checked={Veggies}
/>Veggies<br /><br />
<button onClick={this.handleClearForm}>
Clear Form
</button>
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById("root")
)

Related

Can't update multiple state properties at the same time on my React App

I do this project from this course and I want to increase the possibilities of the app by giving the user the ability to insert a birthday person by putting the name, age and photo with a HTML form. In order to do so i use this:
import React, { useState } from 'react'
import ReactDOM from 'react-dom'
class MyForm extends React.Component {
constructor(props) {
super(props)
this.state = {
username: '',
age: null,
filename: null,
}
}
myChangeHandler = (event) => {
event.nativeEvent.stopImmediatePropagation()
let nam = event.target.name
let val = event.target.value
console.log('click')
if (nam === 'age') {
if (!Number(val)) {
alert('Your age must be a number')
}
}
this.setState({
[nam]: val,
file: URL.createObjectURL(event.target.files[0]),
})
}
render() {
return (
<div className="form">
<form>
<h1 className="title">
Today is the Birtday of {this.state.username} of {this.state.age}{' '}
Years Old
</h1>
<img src={this.state.file} alt="Birtday Pic" />
<p>Enter the name of the Birtday Person:</p>
<input type="text" name="username" onChange={this.myChangeHandler} />
<p>Enter his/her age:</p>
<input type="text" name="age" onChange={this.myChangeHandler} />
<p>Click on the chosen button to send the birtday pic</p>
<input
type="file"
id="myFile"
name="filename"
onChange={this.myChangeHandler}
></input>
<button
type="button"
onClick={() => document.getElementById('myFile').click()}
className="send"
>
Send the Birtday Picture
</button>
<input type="submit" value="Submit"></input>
</form>
</div>
)
}
}
export default MyForm
But here is the issue,I can insert the image but when I tring to put name or age this happends:
I am just a rookie with React, maybe this is some silly thing, maybe I don't use well setState(), but I can't see the issue right now
You're using the same setState for every change:
this.setState({
[nam]: val,
file: URL.createObjectURL(event.target.files[0]),
})
HOWEVER, not every event will have .files - only the change handler used by the file input.
I would make a separate change handler for the file input. Have one for text inputs, and one for file inputs.
For example, for file inputs:
myFileChangeHandler = (event) => {
event.nativeEvent.stopImmediatePropagation()
let nam = event.target.name
let val = event.target.value
this.setState({
[nam]: val,
file: URL.createObjectURL(event.target.files[0]),
})
}
and this for text inputs:
myTextChangeHandler = (event) => {
event.nativeEvent.stopImmediatePropagation()
let nam = event.target.name
let val = event.target.value
if (nam === 'age') {
if (!Number(val)) {
alert('Your age must be a number')
}
}
this.setState({
[nam]: val,
})
}

Why does my React form auto-refresh the page even if I put "event.preventDefault()" on handleSubmit?

I have two files which work together to render things. The first is App.js, which first renders Form.js. The form will then collect information, which on submission, changes the Form state and calls a function from App.js. This function is called "createProject." Calling "createProject" in Form.js "handleSubmit" makes the page auto-refresh. However, if I remove "createProject" from handleSubmit, the page does not auto-refresh. Here are the two files.
import React, { Component } from "react";
import Project from "./components/Project.js"
import Form from "./Form.js";
class App extends Component {
constructor(props) {
super(props);
this.state = {
projectList: [],
myProjects: [],
userList: [],
submitted: false
};
this.createProject = this.createProject.bind(this);
}
createProject(title, desc, langs, len, exp) {
this.setState({
projectList: this.state.projectList.push([
{
title : title,
description : desc,
language : langs,
length : len,
experience : exp
}
]),
submitted : true
});
}
deleteProject(title) {
const projects = this.state.projectList.filter(
p => p.title !== title
);
this.setState({projects});
}
render() {
let info;
if (this.state.submitted) {
info = (
<div>
<p>cccc</p>
</div>
);
} else {
info = (
<br/>
);
}
return(
<div>
<Form/>
{info}
{this.state.projectList.map((params) =>
<Project {...params}/>)}
</div>
);
}
}
export default App;
import React from "react";
import createProject from "./App.js"
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
title: "",
description: "",
language: "",
length: 0,
experience: "",
submitted: false
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
handleSubmit(event) {
this.setState({
submitted: true
})
createProject(
this.state.title,
this.state.description,
this.state.language,
this.state.length,
this.state.experience
)
event.preventDefault();
}
handleInputChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
let info;
if (this.state.submitted) {
info = (
<div>
<h1>{this.state.title}</h1>
<p>{this.state.description}</p>
<p>{this.state.language}</p>
<p>{this.state.length}</p>
<p>{this.state.experience}</p>
</div>
);
} else {
info = <br/>;
}
return (
<div>
<form onSubmit={this.handleSubmit}>
<label>
Title:
<input
name="title"
type="textbox"
checked={this.state.title}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Description:
<input
name="description"
type="textbox"
checked={this.state.description}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Language:
<input
name="language"
type="textbox"
checked={this.state.language}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Length:
<input
name="length"
type="number"
checked={this.state.length}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Experience:
<input
name="experience"
type="textbox"
checked={this.state.experience}
onChange={this.handleInputChange} />
</label>
<br />
<input type="submit" value="Submit" />
</form>
{info}
</div>
);
}
}
export default Form;
I've also tried adding "new" to the "createProject" in handleSubmit, and while that does stop the auto-refresh, it will not call the createProject function. (Or maybe it does, but none of the code in the createProject function seems to be run.) Can anyone help with preventing this auto refresh while also allowing App's createProject function to run properly?
The page auto refreshes because execution never gets to your event.PreventDefault() line. This is due to an error encountered when react tries to evaluate createProject. To fix this, correct handleSubmit like so.
handleSubmit(event) {
event.preventDefault(); // moved up in execution.
this.setState({
submitted: true
})
createProject(
this.state.title,
this.state.description,
this.state.language,
this.state.length,
this.state.experience
)
}
Notice that moving event.PreventDefault() to the top of your handleSubmit(event) function just before this.setState line prevents default form behaviour on submit.
You however get an error because App.js doesn't export a function called createProject. To maintain the createProject within App instance, you need to pass it as a prop which you can then reference as this.props.createProject.
See this answer on how to do call a Parent method in ReactJS.

Adding an input tag dynamically in React, shows for a moment then disappears

What am trying to do is to be able to add an input field dynamically.
So for example, once you fill your first hobby, then you decide to add another one. you click on add and a new input field is shown.
The input field is showing for split second then disappearing.
Code:
class App extends React.Component {
state = {
Hobbies: []
}
addHobby = () => {
this.setState(prevState => ({ Hobbies: [...prevState.Hobbies, ''] }))
}
handleChange(i, event) {
let Hobbies = [...this.state.Hobbies];
Hobbies[i] = event.target.value;
this.setState({ Hobbies });
}
removeClick(i) {
let Hobbies = [...this.state.Hobbies];
Hobbies.splice(i, 1);
this.setState({ Hobbies });
}
render() {
const widthStyle = {
width: '15rem'
};
return (
<div className="App">
<form >
<label>
Hobbies:
<input type="text" name="hobby" />
</label>
<br /><br />
{
this.state.Hobbies.map((el, i) => {
return (
<div key={i}>
<input type="text" value={el || ''} onChange={this.handleChange.bind(this, i)} />
<input type='button' value='remove' onClick={this.removeClick.bind(this, i)} />
</div>
)
})
}
<button onClick={this.addHobby.bind(this)}>ADD Hobby</button>
</form>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('container'));
The problem is you are clicking inside a form which is why your page is getting refreshed(form submits) and you lose the state
addHobby = (e) => {
e.preventDefault() //<-----
this.setState({ Hobbies: [...this.state.Hobbies, ''] })
}
CodeSandbox
An alternative to using e.preventDefault() is to mark the button as being of type="button" the default inside a <form> element is type="submit" which automatically submits the form/refreshes the page.
<button type="button" onClick={this.addHobby.bind(this)}>ADD Hobby</button>
Setting `type="button" indicates that the button is just there to trigger some JavaScript action, not to submit the form.

How to highlight empty mandatory(*) input field with red border click on button in React?

In below image screenshot I make fields mandatory so click on register button If any fields then that empty field I want to highlight with red border in React how it is possible ?
(https://blueprintjs.com/docs/#core/components/text-inputs)
constructor(props) {
super(props);
this.state = {
firstName: '',
lastName: '',
email: '',
password: '',
};
this.handleChange = this.handleChange.bind(this);
this.registerForm = this.registerForm.bind(this);
}
handleChange(event) {
this.setState({[event.target.name]: event.target.value});
}
registerForm(){
if(this.state.firstName.trim() && this.state.lastName.trim() &&
this.state.email && this.state.password){
console.log("registration successfully..!!");
}else{
console.log("all * marked fields mandatory");
}
}
render() {
return (
<div>
<h2>Fill Registration Details..!!</h2>
<InputGroup placeholder="Enter First Name...*"
name="firstName" value={this.state.firstName} onChange={this.handleChange}/>
<InputGroup placeholder="Enter Last Name...*" name="lastName"
value={this.state.lastName} onChange={this.handleChange}/>
<InputGroup placeholder="Enter your email...*" name="email"
value={this.state.email} onChange={this.handleChange}/>
<InputGroup placeholder="Enter your password...*"name="password"
value={this.state.password} onChange={this.handleChange}/>
<Button intent="Primary" onClick={this.registerForm}>Register</Button>
</div>
)
}
One solution, as #Saraband stated, is to modify your node's class name depending on whether or not your input field contains an error:
<InputGroup
placeholder="Enter your password...*"
name="password"
className={this.state.password.length ? '' : 'error'}
value={this.state.password}
onChange={this.handleChange}
/>
You can then use it with the following CSS that will show a red border (for example) :
.error input
{
border-bottom: 1px solid #eb516d;
}
Another way is to use the native required attribute of the input tag, but this method is hard to customize :
<input type='text' required/>
https://www.w3schools.com/tags/att_input_required.asp
For those who might be looking for a solution to this question, the solution below will only validate once the submit button is clicked. You can add a custom css class to style the input tag.
import React, { useState } from 'react';
const ValidateInput = () => {
// set isSubmitting to false by default
// this will make sure error class is not added by default
const [isSubmitting, setIsSubmitting] = useState(false);
const [inputValue, setInputValue] = useState('');
const submitHandler = (event) => {
event.preventDefault();
// this will trigger the error validation
setIsSubmitting(true);
// add the rest of the logic here
};
return (
<form onSubmit={submitHandler}>
<input
value={inputValue}
onChange={(event) => {
setInputValue(event.target.value);
}}
className={isSubmitting && !inputValue ? 'error' : undefined}
/>
<button type="submit">Submit</button>
</form>
);
};
export default ValidateInput;
You can create a CSS class - let's say .red-border and add it to your input whenever their value is empty (your component need to be able to use this className prop and pass it down to your <input /> native component)
<InputGroup
placeholder="Enter your password...*"
name="password"
className={!this.state.password.length ? '' : 'red-border'}
value={this.state.password}
onChange={this.handleChange}
/>
Although it can be best to keep this sort of thing inside your InputGroup component thus confining the logic of your component to a single file
class InputGroup extends React.Component {
// code
render () {
return(
// code
<input
value={this.props.value}
className={!this.state.password.length ? '' : 'red-border'}
/>
);
}
};

Unable to type into React input field

I am unable to type any input into my input field. I am using React, and have already set a handleChange and a handleSubmit function. The first two input fields, for 'name' and 'email', take input just fine. But for 'favoriteCity', it doesn't seem to work.
I am wondering if it is due to a MongoDB error that I am getting.
class UserPage extends Component {
state = {
user: [],
newUser: {
name: '',
email: '',
favoriteCity: ''
}
}
getAllUsers = () => {
axios.get('/api/users')
.then(res => {
this.setState({ user: res.data })
})
}
componentDidMount() {
this.getAllUsers()
}
handleChange = event => {
const newUser = { ...this.state.newUser };
newUser[event.target.name] = event.target.value;
this.setState({ newUser: newUser});
}
handleSubmit = event => {
event.preventDefault()
axios.post('/api/users', this.state.newUser)
.then(res => {
this.props.history.push(`/users/${res.data._id}`)
})
}
render() {
return (
<div>
{ /* This shows a list of All Users */ }
{this.state.user.map(user => (
<div key={user._id}>
<Link to={`/users/${user._id}`}>{user.name}</Link>
</div>
))}
<h1>New User Page</h1>
<form onSubmit={this.handleSubmit}>
<label>Name: </label>
<input
type="text"
name="name"
placeholder="Name?"
value={this.state.newUser.name}
onChange={this.handleChange}
/>
<label>Email: </label>
<input
type="text"
name="email"
placeholder="Email?"
value={this.state.newUser.email}
onChange={this.handleChange}
/>
<label>Favorite City: </label>
<input
type="text"
name="city"
placeholder="Favorite City?"
value={this.state.newUser.favoriteCity}
onChange={this.handleChange}
/>
<Button
type="submit"
value="Submit"
variant="contained"
color="primary"
>
Create User
</Button>
</form>
</div>
);
}
}
export default UserPage;
Please help.
Weird that email works fine, from what you posted your handleChange function is only updating the name on the newUser.
What you should see is what you type in all the inputs appear in the name input.
To fix this, you should probably have separate change handlers for each input:
handleNameChange
handleEmailChange
...
You should also consider storing name, email etc.. at the root of your state instead of nesting them in an object, that'll simplify the handler functions code.

Categories

Resources