¿How to get Form values from functional component React? - javascript

I'm trying to make a table that receives a new user data that is got in a form.
Heres is my code:
import React,{useState} from 'react'
export default function FormAdd({callbackSubmit,...props}) {
const [user,setUser] = useState({});
const handleChangeInput = (name,value) => {
setUser((last) => {
[name]:value,
}
);
}
return (
<form
onSubmit={
(e)=>{
e.preventDefault();
callbackSubmit(user)
}
}
className="formadd-container"
>
<input onChange={(e)=>{handleChangeInput(e.target.name,e.target.value)}} name={"firstname"} placeholder="Fist Name" type="text" className="formadd-container__input"/>
<input onChange={(e)=>{handleChangeInput(e.target.name,e.target.value)}} name={"age"} placeholder="Age" type="text" className="formadd-container__input"/>
<input onChange={(e)=>{handleChangeInput(e.target.name,e.target.value)}} name={"gender"} placeholder="Gender" type="text" className="formadd-container__input"/>
<input onChange={(e)=>{handleChangeInput(e.target.name,e.target.value)}} name={"phone"} placeholder="Phone" type="text" className="formadd-container__input"/>
<input value="Add" type="submit" className="formadd-container__button"/>
</form>
)
}
I get an error >expected ";" inside handleChangeInput function, when I try to set the values for the user object.
Any ideas?

You miss the return in the setState callback.
Replace this :
const handleChangeInput = (name,value) => {
setUser((last) => {
[name]:value,
}
);
}
By:
const handleChangeInput = (name,value) => {
setUser((last) => ({
[name]:value,
})
);
}

Related

Check if html input tag is required

In my react js application i have the next input:
<input required type="text" id="fname" name="fname" value=""/>
In the case above if the form will be submitted the without input value the will appear a message: Please fill in this field, because it is required. Instead of this text i want to add a custom html element with a different content and style.
I want to check after the form is submitted that this input is required and there is no value. So if there is that scenario then to show a custom element bellow like: <div>No data here</div>
I need to achieve this without using the form tag just to create a custom input component in React js and to do something like:
export default function Input() {
const ref = React.useRef();
return (
<div className="App">
<input ref={ref} required type="text" id="fname" name="fname" value=""/>
{ref.current.isError ? <div>Message</div> : null}
</div>
);
}
Is this possible to check?
You can use onInvalid method on input e.g:
function Input() {
const [invalid, setInvalid] = useState<boolean>(false);
const onSubmit = (data: any) => {
setInvalid(false);
console.log(data)
}
return (
<div style={{ margin: '60px'}}>
<form onSubmit={onSubmit}>
<input
id="fname"
name="fname"
required
type="text"
onInvalid={(e) => {
e.preventDefault();
// if you have ref you can obtain reason why this input is invalid
// console.log(ref.current?.validity.valueMissing);
// or just use e.target.validity
setInvalid(true);
}}
/>
<button type="submit">submit</button>
</form>
{invalid && "invalid"}
</div>
);
}
useState is used here to cause re-render component
Edit: if you don't want to have form inside Input component then just move state to parent component e.g:
function Input(props: { invalid: boolean; setInvalid: () => void }) {
const { invalid, setInvalid } = props;
return (
<div style={{ margin: '60px'}}>
<input
id="fname"
name="fname"
required
type="text"
onInvalid={(e) => {
e.preventDefault();
setInvalid();
}}
/>
{invalid && "invalid"}
</div>
);
}
function App() {
const [invalid, setInvalid] = useState<Record<string, boolean>>({});
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
setInvalid({});
console.log(event);
}
return (
<div className="App">
<form onSubmit={handleSubmit}>
<Input invalid={invalid.fname} setInvalid={() => setInvalid(state => ({...state, fname: true}))}/>
<button type="submit">submit</button>
</form>
</div>
);
}
Edit2: If you want make it valid again you can use onChange:
function Input() {
const [invalid, setInvalid] = React.useState(false);
const updateInvalid = (e) => setInvalid(!e.nativeEvent.target.validity.valid);
return (
<div>
<input
id="fname"
name="fname"
required
type="text"
onChange={updateInvalid}
onInvalid={(e) => {
e.preventDefault();
updateInvalid(e);
}}
/>
<div>{invalid && "Invalid"}</div>
</div>
);
}
Sandbox
All you need is to check if the input is empty or not and based on result we are making a decision for printing message.
All we need is useState hook, onSubmit form validation.
index.js
import React from "react";
import ReactDOM from "react-dom";
import MyInput from "./MyInput.js";
class App extends React.Component {
render() {
return (
<div>
// validate attribute to defind which validation we need
<MyInput validate="email" />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("container"));
MyInput.js
import React, { useState } from "react";
const MyInput = ({ validate }) => {
const [userInput, setUserInput] = useState("");
const [isError, setIsError] = useState(false);
const [errorMessage, setErrorMessage] = useState("");
const handleInput = (e) => {
setUserInput(e.target.value);
setIsError(false);
};
function validateEmail(email) {
var re = /\S+#\S+\.\S+/;
return re.test(email);
}
//you can defind more states such as for password or as per your requirement.
const validateField = (fieldType) => {
switch (fieldType) {
case "email":
if (validateEmail(userInput)) {
setIsError(false);
} else {
setErrorMessage("Need proper email..");
setIsError(true);
}
break;
default:
setIsError(false);
}
};
const handleSubmit = (e) => {
e.preventDefault();
validateField(validate);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" value={userInput} onChange={handleInput} />
{isError ? <p>{errorMessage}</p> : ""}
<input type="submit" />
</form>
);
};
export default MyInput;
Here is working example.
<iframe src="https://codesandbox.io/embed/react-playground-forked-ozgle5?fontsize=14&hidenavigation=1&theme=dark&view=preview" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" title="React PlayGround (forked)" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>

How to pass a value in a form OnPost method React

const afterSubmission = (e, message) => {
e.preventDefault()
console.log(message);
if (message === "") return
displayMessage(message)
messageInput.value=""
}
<div id="message-container"></div>
<form onSubmit = {afterSubmission}>
<label for="message-input">Message</label>
<input type="text" id="message-input" />
<button type="submit" id="send-button">Send</button>
</form>
I have these two pieces of code, my question is how can I pass the value from the input tag in the form to the afterSubmission method?
Assuming this is the same component, an easy solution would be to use state.
Your code snippets aren't very useful, just as an FYI for future questions, but here's an example of me tracking form state.
import { useState } from "react";
export default function App() {
const [message, setMessage] = useState("test");
const handleChange = (e) => {
setMessage((old) => e.target.value);
};
const afterSubmission = (e) => {
e.preventDefault();
console.log(message);
};
return (
<div className="App">
<form onSubmit={afterSubmission}>
<input
type="text"
id="message-input"
value={message}
onChange={handleChange}
/>
<button
type="submit"
id="send-button"
>
Send
</button>
</form>
</div>
);
}
As you can see, this tracks your message in the component's state which makes it accessible in the afterSubmission function.

How do I pass my Form Data which is in the child component to the parent component(which also contains a form) and on submit log all the data?

So I have a parent component which contains a form and a child component(this component also has a form , here its a dynamic form meaning when the add button is hit it creates another form below so that user can add a list of parameters of various types . Basically I am trying to achieve state lifting from child to component . I would be really grateful if someone could help me out , I have been stuck on this since a week and I tried a lot . I would appreciate if someone could refactor my code so that it works . I have also attached a gif which shows the form
GIF : https://drive.google.com/file/d/15YXGhvo0OMCh4ch44q4S88wcqOB7i2ew/view?usp=sharing
Parent Component - ParamsForm.js
import React, { useState, useEffect } from 'react'
import { Form } from 'react-bootstrap'
import styles from '../style.module.css'
import Operations from './Operations'
import OperationsFormTest from './OperationsFormTest'
const ParamsForm = () => {
const[isToggled,setIsToggled] = useState(false)
const[formData,setFormData] = useState(
{url:'',endpoint:'',name:'',description:'',type:'',required:''}
)
const handleSubmit = (e) =>{
e.preventDefault()
console.log('Form Data is :' , formData)
}
const handleChangeInput = (index,e) =>{
const values = [...formData]
values[index][e.target.name] = e.target.value
setFormData(values)
}
const handleAddFields = () =>{
setFormData([...formData,{url:'',endpoint:'',name:'',description:'',type:'',required:''}])
}
const handleRemoveFields = (index) =>{
const values = [...formData]
values.splice(index,1)
setFormData(values)
}
useEffect(()=>{
console.log(isToggled)
},[isToggled])
return (
<div className={styles.paramFormsContainer}>
{setFormData}
<form onSubmit={handleSubmit}>
<input type='text' name='url' placeholder='Url..' value={formData.url} onChange={handleChangeInput}></input>
<input type='text' name='endpoint' placeholder='Endpoint...' value={formData.endpoint} style={{flex : 1 }} onChange={handleChangeInput}></input>
<button type='button' onClick={()=>setIsToggled(!isToggled)} className={styles.pathParamFormsBtn}>Path Params</button>
{isToggled && <OperationsFormTest name={formData.name} description={formData.description} type={formData.type} required={formData.required} handleAddFields={handleAddFields} nameFunc={handleChangeInput} descriptionFunc={handleChangeInput} typeFunc={handleChangeInput} requiredFunc={handleChangeInput} handleRemoveFields={handleRemoveFields}></OperationsFormTest>}
<br></br><br></br>
<button type='submit' onClick={handleSubmit}>Submit</button>
</form>
</div>
)
}
export default ParamsForm
Child Component - OperationsFormTest.js
import React, { useEffect, useState } from 'react'
import styles from '../style.module.css'
import {FaInfo,FaFileInvoiceDollar} from 'react-icons/fa'
import ReactTooltip from "react-tooltip";
const OperationsFormTest = ({name,type,description,required,nameFunc,descriptionFunc,typeFunc,requiredFunc,handleAddFields,handleRemoveFields}) =>{
const ChildToParentName = (e) =>{
nameFunc(e)
}
const ChildToParentType = (e) =>{
typeFunc(e)
}
const ChildToParentDescription = (e) =>{
descriptionFunc(e)
}
const ChildToParentRequired = (e) =>{
requiredFunc(e)
}
return(
<>
<div>
<div className={styles.pathParamsFormParentContainer}>
<div className={styles.pathParamsFormChildContainer}>
<label>Name : </label>
<input name='name' type='text' placeholder='Name..' value={name} onChange={ChildToParentName}></input><br></br><br></br>
<label>Description : </label>
<input name='description' type='text' placeholder='Description..' value={description} onChange={ChildToParentDescription}></input><br></br><br></br>
<select name = 'type' value = {type} onChange={ChildToParentType}>
<option>Any</option>
<option>String</option>
<option>Boolean</option>
</select>
<label>Required : </label>
<input name='required' type='text' placeholder='Yes or No..' value={required} onChange={ChildToParentRequired}></input><br></br><br></br>
<button type='button' onClick={()=>handleAddFields()}>Add</button>
<button type='button' onClick={()=>handleRemoveFields()}>Remove</button><br></br><br></br>
</div>
</div>
</div>
</>
)
}
export default OperationsFormTest
I hope you will get some idea from this simple codes.
function Home() {
// Async await is up to you
const onSubmit = async (data)=> {
console.log(data);
}
return (
<Form onSubmit={onSubmit} />
)
}
function Form() {
const [text,setText] = useState("");
// async await is up to you
const handleSubmit = async (e)=> {
e.preventDefault();
await onSubmit(text);
setText("");
}
return (
<form onSubmit={handleSubmit}>
<input type={"text"} value={text} onChange={e=>setText(e.target.value)} />
<input type={"submit"} />
</form>
)
}

Reset form input values in React

I want create a function using with i can reset value in form inputs without submit. I tried create that function in App Component (resetFormFields) and pass it on props to Form Component. It's preety simply when I want to do this onSubmit (e.target.reset()) but I got stuck when I have to do it without submit, on a different element than the form. Can I do that without adding these values to state?
App:
class App extends Component {
state = {
people: [],
formMessages: [],
person: null
};
handleFormSubmit = e => {
e.preventDefault();
const form = e.target;
const name = form.elements["name"].value;
const username = form.elements["username"].value;
this.addPerson(name, email);
form.reset();
};
resetFormFields = () => {
return;
}
render() {
return (
<div className="App">
<Form formSubmit={this.handleFormSubmit}
reset={this.resetFormFields} />
</div>
);
}
Form:
const Form = props => (
<form className={classes.Form}
id="form"
onSubmit={props.formSubmit}>
<input autoFocus
id="name"
type="text"
defaultValue=""
placeholder="Name..."
/>
<input
id="email"
type="text"
defaultValue=""
placeholder="Email..."
/>
<Button
btnType="Submit"
form="form"
type='submit'>
Submit
</Button>
<label onClick={props.reset}>Reset fields</label>
</form> );
onHandleFormSubmit = (e) =>{
e.preventDefault();
e.target.reset();
}
You need to make your inputs controlled by passing the value you store in your state then you just have to reset the state values and your component value resets.
check this sample below
handleInputChange = (e) => {
let { name, value } = e.target;
this.setState({
...this.state,
inputs: {
[name]: value
}
});
}
your component will now look like
<input name='fullName' value={this.state.inputs.fullName} onChange={this.handleInputChange} />
Your reset function will just clear the state and your input field will be empty since it's controlled via state
resetInputFields = () => {
this.setState({ inputs: {} })
}
you should give set your input values based on component state, then just update the component state
class App extends Component {
state = {
people: [],
formMessages: [],
person: null,
name: "",
email: "",
};
updateState = (newState) => {
this.setState(newState);
}
handleFormSubmit = e => {
e.preventDefault();
this.addPerson(this.state.name, this.state.email);
form.reset();
};
resetFormFields = () => {
this.setState({name:"", email: ""});
}
render() {
return (
<div className="App">
<Form formSubmit={this.handleFormSubmit} updateState={this.updateState}
reset={this.resetFormFields} email={this.state.email} name={this.state.name} />
</div>
);
}
and then
const Form = props => (
<form className={classes.Form}
id="form"
onSubmit={props.formSubmit}>
<input autoFocus
id="name"
type="text"
defaultValue=""
value={this.props.name}
onChange={(e) => this.props.updateState({name: e.target.value})}
placeholder="Name..."
/>
<input
id="email"
type="text"
defaultValue=""
value={this.props.email}
onChange={(e) => this.props.updateState({email: e.target.value})}
placeholder="Email..."
/>
<Button
btnType="Submit"
form="form"
type='submit'>
Submit
</Button>
<label onClick={props.reset}>Reset fields</label>
</form> );

Clear an input field with Reactjs?

I am using a variable below.
var newInput = {
title: this.inputTitle.value,
entry: this.inputEntry.value
};
This is used by my input fields.
<input type="text" id="inputname" className="form-control" ref={el => this.inputTitle = el} />
<textarea id="inputage" ref={el => this.inputEntry = el} className="form-control" />
<button className="btn btn-info" onClick={this.sendthru}>Add</button>
Once I activate {this.sendthru} I want to clear my input fields. However, I am uncertain how to do so.
Also, as shown in this example, it was pointed out to me that I should use the ref property for input values. What I am unclear of is what exactly does it mean to have {el => this.inputEntry = el}. What is the significance of el in this situation?
Let me assume that you have done the 'this' binding of 'sendThru' function.
The below functions clears the input fields when the method is triggered.
sendThru() {
this.inputTitle.value = "";
this.inputEntry.value = "";
}
Refs can be written as inline function expression:
ref={el => this.inputTitle = el}
where el refers to the component.
When refs are written like above, React sees a different function object each time so on every update, ref will be called with null immediately before it's called with the component instance.
Read more about it here.
Declare value attribute for input tag (i.e value= {this.state.name}) and if you want to clear this input value you have to use this.setState({name : ''})
PFB working code for your reference :
<script type="text/babel">
var StateComponent = React.createClass({
resetName : function(event){
this.setState({
name : ''
});
},
render : function(){
return (
<div>
<input type="text" value= {this.state.name}/>
<button onClick={this.resetName}>Reset</button>
</div>
)
}
});
ReactDOM.render(<StateComponent/>, document.getElementById('app'));
</script>
I'm not really sure of the syntax {el => this.inputEntry = el}, but when clearing an input field you assign a ref like you mentioned.
<input type="text" ref="someName" />
Then in the onClick function after you've finished using the input value, just use...
this.refs.someName.value = '';
Edit
Actually the {el => this.inputEntry = el} is the same as this I believe. Maybe someone can correct me. The value for el must be getting passed in from somewhere, to act as the reference.
function (el) {
this.inputEntry = el;
}
I have a similar solution to #Satheesh using React hooks:
State initialization:
const [enteredText, setEnteredText] = useState('');
Input tag:
<input type="text" value={enteredText} (event handler, classNames, etc.) />
Inside the event handler function, after updating the object with data from input form, call:
setEnteredText('');
Note: This is described as 'two-way binding'
You can use input type="reset"
<form action="/action_page.php">
text: <input type="text" name="email" /><br />
<input type="reset" defaultValue="Reset" />
</form>
Now you can use the useRef hook to get some magic if you do not want to use the useState hook:
function MyComponent() {
const inputRef = useRef(null);
const onButtonClick = () => {
// #ts-ignore (us this comment if typescript raises an error)
inputRef.current.value = "";
};
return (
<>
<input ref={inputRef} type="text" />
<button onClick={onButtonClick}>Clear input</button>
</>
);
}
As I mentioned, if you are using useState that is the best way. I wanted to show you also this special approach.
Also after React v 16.8+ you have an ability to use hooks
import React, {useState} from 'react';
const ControlledInputs = () => {
const [firstName, setFirstName] = useState(false);
const handleSubmit = (e) => {
e.preventDefault();
if (firstName) {
console.log('firstName :>> ', firstName);
}
};
return (
<>
<form onSubmit={handleSubmit}>
<label htmlFor="firstName">Name: </label>
<input
type="text"
id="firstName"
name="firstName"
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
<button type="submit">add person</button>
</form>
</>
);
};
You can use useState:
import React, { useState } from 'react';
const [inputTitle, setInputTitle] = useState('');
then add value to your input component:
render() {
<input type="text" onChange={(e) => setInputTitle(e.target.value)}
value={inputTitle} />
<button onClick={handleSubmit} type="submit">Submit</button>
}
On your submit handler function:
setInputTitle('');
document.querySelector('input').defaultValue = '';
On the event of onClick
this.state={
title:''
}
sendthru=()=>{
document.getElementByid('inputname').value = '';
this.setState({
title:''
})
}
<input type="text" id="inputname" className="form-control" ref={el => this.inputTitle = el} />
<button className="btn btn-info" onClick={this.sendthru}>Add</button>
I used the defaultValue property, useRef, and onClick to achieve this.
let ref = useRef()
and then inside the return:
<input type="text" defaultValue="bacon" ref={ref} onClick={() => ref.current.value = ""} />
also if you want to use onChange for the input it wouldn't require any more configuration and you can just use it. If you want to have a dynamic defaultValue then you absolutely can, with useState.
A simple way to reset the input in React is by implementing the onBlur inside the input.
onBlur={cleanSearch}
ej:
const [search, setSearch] = useState('')
const handleSearch = ({target}) =>{
setSearch(target.value)
}
const cleanSearch = () =>setSearch('')
<input
placeholder="Search…"
inputProps={{ 'aria-label': 'search' }}
value={search}
onChange={handleSearch}
onBlur={cleanSearch}
/>
The way I cleared my form input values was to add an id to my form tag.
Then when I handleSubmit I call this.clearForm()
In the clearForm function I then use document.getElementById("myForm").reset();
import React, {Component } from 'react';
import './App.css';
import Button from './components/Button';
import Input from './components/Input';
class App extends Component {
state = {
item: "",
list: []
}
componentDidMount() {
this.clearForm();
}
handleFormSubmit = event => {
this.clearForm()
event.preventDefault()
const item = this.state.item
this.setState ({
list: [...this.state.list, item],
})
}
handleInputChange = event => {
this.setState ({
item: event.target.value
})
}
clearForm = () => {
document.getElementById("myForm").reset();
this.setState({
item: ""
})
}
render() {
return (
<form id="myForm">
<Input
name="textinfo"
onChange={this.handleInputChange}
value={this.state.item}
/>
<Button
onClick={this.handleFormSubmit}
> </Button>
</form>
);
}
}
export default App;

Categories