How to pre-populate fields on click of a button in react? - javascript

I am trying to pre-populate the form fields, that are replicated, from the fields that are already filled. On clicking the "Add fields" button, the fields are getting replicated. But I want them to get pre-populated using the data filled in the already existing fields.
From where can I get hold of the input values?
import './style.css';
export default function App() {
const [inputFields, setInputFields] = useState([{ name: '', age: '' }]);
const addFields = (e) => {
e.preventDefault();
let newField = { name: "", age: '' };
setInputFields([...inputFields, newField]);
};
const handleFormChange = (index, e) => {
let data=[...inputFields];
data[index][e.target.name]=[e.target.value];
setInputFields(data);
}
return (
<div>
<form>
{inputFields.map((input, index) => {
return (
<div key={index}>
<input
type="text"
name="name"
placeholder="Enter name"
value={input.name}
onChange={(e)=>handleFormChange(index, e)}
/>
<input
type="number"
name="age"
placeholder="Enter Age"
value={input.age}
onChange={(e)=>handleFormChange(index, e)}
/>
<br />
<br />
</div>
);
})}
<button onClick={addFields}>Add Field</button>
<br />
</form>
</div>
);
}```

You will need to track changes in input with an onChange handler.
Also, you are not setting values from the last input fields anywhere to be able to duplicate them. The below code might work as you expect:
const { useState } = React;
function App() {
const [inputFields, setInputFields] = useState([{ name: '', age: '' }]);
const addFields = (e) => {
e.preventDefault();
const temp = inputFields.slice()
, length = temp.length - 1
, { name, age } = temp[length]
// Set value from last input into the new field
let newField = { name, age }
setInputFields([...temp, newField])
}
, handleChange = (index, event) => {
const temp = inputFields.slice() // Make a copy of the input array first.
inputFields[index][event.target.name] = event.target.value // Update it with the modified values.
setInputFields(temp) // Update the state.
};
return (
<div>
<form>
{inputFields.map((input, index) => {
return (
<div key={index}>
<input
onChange={e => handleChange(index, e)}
value={input.name}
type="text"
name="name"
placeholder="Enter name"
/>
<input
onChange={e => handleChange(index, e)}
value={input.age}
type="number"
name="age"
placeholder="Enter Age"
/>
<br />
<br />
</div>
);
})}
<button onClick={addFields}>Add Field</button>
<br />
</form>
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

You have to set the value property on the input field to populate, e.g:
<input
value={input.name}
type="text"
name="name"
placeholder="Enter name"
/>

Related

How to update state if I have props coming from parent component in React Hooks

I am trying to get updated textbox value if I have props from parent component.
Here is my code -
const initialState = {
name: "",
age: 0
}
const UserAdd = (props:any) => {
const {selectedUser} = props;
const [state, setState] = useState<any>(initialState);
const dispatch = useDispatch();
const onChangeValue = (event:any) => {
const { name, value } = event.target;
setState((prevState:any) => (
{ ...prevState, [name]: value }
));
}
const onSubmit = (e:any) => {
e.preventDefault();
const { name } = e.target;
dispatch(addUser(state.name, state.age))
setState({ ...initialState });
}
const onUpdate = (e:any) => {
e.preventDefault();
const { name } = e.target;
console.log(state.name , state.age , "name-age")
}
return (
<div className="add-user">
<hr />
<h2>Add User</h2>
<hr />
{ selectedUser ?
(<form className="form-inline">
<input type="text" className="form-control mb-2 mr-sm-5 col-md-4" id="email2" placeholder="Enter user name" name="name" value={selectedUser.name} onChange={onChangeValue} />
<input type="text" className="form-control mb-2 mr-sm-5 col-md-4" id="pwd2" placeholder="Enter user age" name="age" onChange={onChangeValue} value={selectedUser.age} />
<button type="submit" onClick={onUpdate} className="btn btn-primary col-md-2 mb-2">Update</button>
</form>)
:
(
<form className="form-inline">
<input type="text" className="form-control mb-2 mr-sm-5 col-md-4" id="email2" placeholder="Enter user name" name="name" value={state.name} onChange={onChangeValue} />
<input type="text" className="form-control mb-2 mr-sm-5 col-md-4" id="pwd2" placeholder="Enter user age" name="age" onChange={onChangeValue} value={state.age} />
<button type="submit" onClick={onSubmit} className="btn btn-primary col-md-2 mb-2">Submit</button>
</form>
)
}
</div>
)
}
export default UserAdd;
When There is no props i.e (no selectedUser), Then state change working fine and I am able to dispatch action as well. But When Props(selectedUser) is available, then I am unable to edit textbox field & unable to get updated state. Please someone help me.
look deeper into your code.. there is different forms when selectedUser is not falsy...
when there is selected user:
value={selectedUser.name}
shouled be like the other form's input:
value={state.name}
u also need to add useEffect to change the state when the prop is being changed, u can do it like so:
useEffect(()=>{
setState((prevState:any) => (
{ ...prevState, name: selectedUser.name}
));
},[selectedUser.name])
the useEffect then will be executed whenever any item of the dependency list will be different from the last render (in this case each time the selectedUser.name is being changed)
In case there is selectedUser, the value attribute of input field should be reactive. Currently, it is set to props that won't react to onChangeValue handler. Use state in the value attribute (state.name /state.age) and initialize states with selectedUser props value. It might look like below -
const initialState = {
name: "",
age: 0
}
const UserAdd = (props:any) => {
const {selectedUser} = props;
//Button text would be Update or submit that depends on selectedUser.
const btnText = selectedUser ? "Update" : "Submit";
//If it founds selected user then set to it otherwise go with initialState
const [state, setState] = useState<any>(selectedUser || initialState);
const dispatch = useDispatch();
const onChangeValue = (event:any) => {
const { name, value } = event.target;
setState((prevState:any) => (
{ ...prevState, [name]: value }
));
}
const onSubmit = (e:any) => {
e.preventDefault();
const { name } = e.target;
dispatch(addUser(state.name, state.age))
setState({ ...initialState });
}
return (
<div className="add-user">
<hr />
<h2>Add User</h2>
<hr />
<form className="form-inline">
<input type="text" className="form-control mb-2 mr-sm-5 col-md-4" id="email2" placeholder="Enter user name" name="name" value={selectedUser.name} onChange={onChangeValue} />
<input type="text" className="form-control mb-2 mr-sm-5 col-md-4" id="pwd2" placeholder="Enter user age" name="age" onChange={onChangeValue} value={selectedUser.age} />
<button type="submit" onClick={onUpdate} className="btn btn-primary col-md-2 mb-2">{btnText}</button>
</form>
</div>
)
}
export default UserAdd;
Once you set it up like this you don't need to render forms conditionally. you only need one form. I have added a few comments as well. I have created a working POC here https://codesandbox.io/s/propstostate-react-ssirn

how to set props values of controls in react js

I am new to react. I have almost 15 input controls on UI. Some are dropdowns, some are textboxes, couple of calender controls and radio buttons. I want to retrive all values before submitting a page. Do I need to define 15 props in state object of component for 15 inputs? is there any way to have it in one object.
Also how to set the values of each control. For example for textbox I know, its like
<input type="text" name="username" className="form-control" id="exampleInput" value={this.props.name} onChange={this.handleChange} placeholder="Enter name"></input>
How to handle same for dropdown,calender and radio buttton. Thanks in advance.
Normally, these wouldn't be props, they'd be state (which is different). You can use objects in state. If you're doing a class-based component (class YourComponent extends React.Component), state is always an object you create in the constructor and update with setState. If you're doing this in a function component, typically you use separate state variables for each thing (const [name, setName] = useState("");), but you can use an object if you prefer. There's more about state in the documentation.
That said, if you only want the values when you take an action, you could make the inputs "uncontrolled."
Here's a three-input example using a class component:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
firstName: "",
lastName: "",
about: ""
};
this.handleChange = this.handleChange.bind(this);
}
handleChange({target: {name, value}}) {
this.setState({[name]: value});
}
render() {
const {firstName, lastName, about} = this.state;
const {handleChange} = this;
return <div>
<div>
<label>
First name:
<br/>
<input type="text" value={firstName} name="firstName" onChange={handleChange} />
</label>
</div>
<div>
<label>
Last name:
<br/>
<input type="text" value={lastName} name="lastName" onChange={handleChange} />
</label>
</div>
<div>
<label>
About you:
<br />
<textarea value={about} name="about" onChange={handleChange} />
</label>
</div>
<div>{firstName} {lastName} {(firstName || lastName) && about ? "-" : ""} {about}</div>
</div>;
}
}
ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
Here's one using a functional component with discrete state items (usually best):
const { useState } = React;
const Example = () => {
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [about, setAbout] = useState("");
// There's are lots of ways to do this part, this is just one of them
const handleChange = ({target: {name, value}}) => {
switch (name) {
case "firstName":
setFirstName(value);
break;
case "lastName":
setLastName(value);
break;
case "about":
setAbout(value);
break;
}
};
return <div>
<div>
<label>
First name:
<br/>
<input type="text" value={firstName} name="firstName" onChange={handleChange} />
</label>
</div>
<div>
<label>
Last name:
<br/>
<input type="text" value={lastName} name="lastName" onChange={handleChange} />
</label>
</div>
<div>
<label>
About you:
<br />
<textarea value={about} name="about" onChange={handleChange} />
</label>
</div>
<div>{firstName} {lastName} {(firstName || lastName) && about ? "-" : ""} {about}</div>
</div>;
}
ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
Here's one using a functional component with an object in state:
const { useState } = React;
const Example = () => {
const [data, setData] = useState({firstName: "", lastName: "", about: ""});
const handleChange = ({target: {name, value}}) => {
setData(current => ({...current, [name]: value}));
};
const {firstName, lastName, about} = data;
return <div>
<div>
<label>
First name:
<br/>
<input type="text" value={firstName} name="firstName" onChange={handleChange} />
</label>
</div>
<div>
<label>
Last name:
<br/>
<input type="text" value={lastName} name="lastName" onChange={handleChange} />
</label>
</div>
<div>
<label>
About you:
<br />
<textarea value={about} name="about" onChange={handleChange} />
</label>
</div>
<div>{firstName} {lastName} {(firstName || lastName) && about ? "-" : ""} {about}</div>
</div>;
}
ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
Here is the sample code, I used in my application.
class CreditCardForm extends React.Component {
constructor() {
super()
this.state = {
name: '',
address: '',
ccNumber: ''
}
}
handleChange(e) {
// If you are using babel, you can use ES 6 dictionary syntax
// let change = { [e.target.name] = e.target.value }
let change = {}
change[e.target.name] = e.target.value
this.setState(change)
}
render() {
return (
<form>
<h2>Enter your credit card details</h2>
<label>
Full Name
<input type="name" onChange={(e)=>this.handleChange(e)} value={this.state.name} />
</label>
<label>
Home address
<input type="address" onChange={(e)=>this.handleChange(e)} value={this.state.address} />
</label>
<label>
Credit card number
<input type="ccNumber" onChange={(e)=>this.handleChange(e)} maxlength="16" value={this.state.ccNumber} />
</label>
<button type="submit">Pay now</button>
</form>
)
}
}
You can set name for input and update state base on event.target.name and event.target.value
constructor() {
super();
this.state = {
text: "",
select: "",
radio: ""
};
}
handeInput = e => {
this.setState({
[e.target.name]: e.target.value
});
};
render() {
console.log(this.state);
return (
<div className="App">
<input
onChange={this.handeInput}
type="input"
name="text"
value={this.state.text}
/>
<select
name="select"
onChange={this.handeInput}
value={this.state.select}
>
<option value="option1">option1</option>
<option value="option2">option2</option>
</select>
<input
type="radio"
name="radio"
value="Option1"
checked={this.state.radio === "Option1"}
onChange={this.handeInput}
/>
Option1
<input
type="radio"
name="radio"
value="Option2"
checked={this.state.radio === "Option2"}
onChange={this.handeInput}
/>
Option2
</div>
);
}
You can check here CodeSandBox Hope it helps

Reactjs Dynamic Form Getting Error OnChnage input value?

I am created a dynamic form in react.js but i can not type anything value in input because onchnage function not working i don't know why i tried a lot of times but i am getting failed and adding form and deleting form is working all right only input value not working here is my code and codesandbox link https://codesandbox.io/s/reactdynamicform-02cho .
import React, { Component } from "react";
import "bootstrap/dist/css/bootstrap.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
inputFields: [
{
firstName: "",
lastName: ""
}
]
};
}
handleAddFields = () => {
const values = this.state.inputFields;
values.push({ firstName: "", lastName: "" });
this.setState({
values
});
};
handleRemoveFields = index => {
const values = this.state.inputFields;
values.splice(index, 1);
this.setState({
values
});
};
async onChange(e, index) {
if (
["firstName","lastName"].includes(e.target.name)
) {
let cats = [...this.state.inputFields];
cats[index][e.target.name] = e.target.value;
await this.setState({
cats
});
}else{
this.setState({ [e.target.name]: e.target.value.toUpperCase() });
}
console.log(this.state.inputFields);
}
handleSubmit = e => {
e.preventDefault();
console.log("inputFields", this.state.inputFields);
};
render() {
return (
<>
<h1>Dynamic Form Fields in React</h1>
<form onSubmit={this.handleSubmit.bind(this)}>
<div className="form-row">
{this.state.inputFields.map((inputField, index) => (
<div key={`${inputField}~${index}`}>
<div className="form-group col-sm-6">
<label htmlFor="firstName">First Name</label>
<input
type="text"
className="form-control"
id="firstName"
name="firstName"
value={inputField.firstName}
onChange={this.onChange.bind(index)}
/>
</div>
<div className="form-group col-sm-4">
<label htmlFor="lastName">Last Name</label>
<input
type="text"
className="form-control"
id="lastName"
name="lastName"
value={inputField.lastName}
onChange={this.onChange.bind(index)}
/>
</div>
<div className="form-group col-sm-2">
<button
className="btn btn-link"
type="button"
onClick={() => this.handleRemoveFields(index)}
>
-
</button>
<button
className="btn btn-link"
type="button"
onClick={() => this.handleAddFields()}
>
+
</button>
</div>
</div>
))}
</div>
<div className="submit-button">
<button
className="btn btn-primary mr-2"
type="submit"
// onSubmit={this.handleSubmit}
>
Save
</button>
</div>
<br />
<pre>{JSON.stringify(this.state.inputFields, null, 2)}</pre>
</form>
</>
);
}
}
export default App;
You approach is not the correct. Use object to contain form values
state = {
inputFields: { firstName: '', lastName: '' }
}
onChange = (e) => {
const { name, value } = e.target;
this.setState(prevState => ({ inputFields: { ...prevState.inputFields, [name]: value } }));
}
// in jsx
<input name="firstName" onChange={this.onChange} />
try this
onChange={(e)=>{this.onChange(e, index)}}
instead of
onChange={this.onChange.bind(index)}
1) Since your inputFields state is an array, you can't just call this.state.inputFields.firstName and even less inputField.firstName.
You have to call this.state.inputsFields[0].firstName.
2) If you want the index AND the event, you have to pass the onChange event like this :
<input
type="text"
className="form-control"
id="lastName"
name="lastName"
onChange={event => this.handleChange(event, index)}
/>
handleChange = (event, index) => {
console.log(event.currentTarget.value, index);
};
// output : {whatever you type} {index of the form}
// exemple : "hello 1"

Storing each input's data in its respective state

I have three inputs, and I want each input's data to be stored in a state. For example, the name input should be stored in the name state, because I'll need it later to push the three states' values in a firebase database.
I used the onChange function to store the data, but I didn't know how to make each input's function relative to the state I want to put it in.
import React from "react";
import ReactDOM from "react-dom";
export default class Inputs extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "",
email: "",
age: ""
};
}
handleChange = e => {
this.setState({ name: e.target.value });
};
render() {
return (
<div>
<form>
<label>
name:
<input type="text" name="name" onChange={this.handleChange} />
</label>
<label>
email:
<input type="text" name="email" onChange={this.handleChange} />
</label>
<label>
age:
<input type="text" name="age" onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
<textarea value={this.state.value} onChange={this.handleChange} />
<button onClick={() => this.props.onClick(this.state.value)}>
Add task
</button>
</div>
);
}
}
getChanges = (e) => {
console.log(e);
this.setState({[e.target.name]: e.target.value}, function () {
console.log(this.state)
})
};
call this function,
<Input onChange={(e) => this.getChanges(e)} name={'name'}
value={this.state.name} placeholder={'Name'}/>
You can pass key and value
<input type="text" name="name" onChange={(event)=>this.handleChange(event,'name')} />
and in your function you can do something like this
handleChange = (e,key) => {
this.setState({ [key] : e.target.value });
};

How to process onChange and change focus to new <Field>?

I'm using Formik (with withFormik()) and want to check a <Field> as a user types in it - after it has 4 characters in it, I want to focus on the next field so they can keep typing without having to move to the next field.
So my InnerForm has:
<Field
type="text"
name="credit1"
inputmode="numeric"
maxlength="4" />
<Field
type="text"
name="credit2"
inputmode="numeric"
maxlength="4" />
And my FormikInnerFormContainer = withFormik(...) has a validationSchema.
How could I catch changes on the first field, and move focus to the 2nd field if the first has 4 characters in?
I tried to override the onChange, but couldn't figure out how to update the Field contents with each character the user types.
You might use like this in Formik.
focusChange(e) {
if (e.target.value.length >= e.target.getAttribute("maxlength")) {
e.target.nextElementSibling.focus();
}
...
//Example implementation
import React from "react";
import { Formik } from "formik";
export default class Basic extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
this.focusChange = this.focusChange.bind(this);
}
focusChange(e) {
if (e.target.value.length >= e.target.getAttribute("maxlength")) {
e.target.nextElementSibling.focus();
}
}
render() {
return (
<div>
<h1>My Form</h1>
<Formik
initialValues={{ name: "" }}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
render={props => (
<form onSubmit={props.handleSubmit} ref={this.inputRef}>
<input
type="text"
onChange={props.handleChange}
onBlur={props.handleBlur}
value={props.values.name}
name="name"
maxlength="4"
onInput={e => this.focusChange(e)}
/>
<input
type="text"
onChange={props.handleChange}
onBlur={props.handleBlur}
value={props.values.lastName}
name="lastName"
maxlength="4"
onInput={this.focusChange}
/>
<button type="submit">Submit</button>
</form>
)}
/>
</div>
);
}
}
In vanilla javascript you can do this:
document.querySelectorAll('input').forEach(function(input) {
input.addEventListener('keyup', function() {
if(input.value.length >= input.getAttribute('maxlength'))
input.nextElementSibling.focus();
});
})

Categories