I'm having a lot of troubles trying to render the data I passed into my inputs to render a "contact" card.
I'm handling the inputs, changing the states accordingly, but when it comes to the final state, rendering a "Contact card" with all my data I just don't know how to make it works.
I think the problem is at my "renderCard" method.
If someone could give me a hand I think i'm really close but yet so far..
import React, { Component } from 'react';
export default class Todo extends Component {
state = {
nom: '',
age: '',
ville: '',
items: [],
start: 0
};
onChange = (event) => {
this.setState({
[event.target.name]: event.target.value
});
}
onSubmit = (event) => {
event.preventDefault();
this.setState({
nom: '',
age: '',
ville: '',
items: [...this.state.items, this.state.nom, this.state.age, this.state.ville],
start: 1
});
}
renderCard = () => {
return this.state.items.map((item, index) => {
return (
<div className="card" key={index}>
{item.nom}
{item.age}
{item.ville}
</div>
);
});
}
render() {
return (
<div>
<div className="card mb-3">
<div className="card-header">Ajouter une Personne</div>
<div className="card-body">
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label htmlFor="name">Nom</label>
<input
type="text"
className="form-control form-control-lg"
name="nom"
value={this.state.nom}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label htmlFor="name">Age</label>
<input
type="text"
className="form-control form-control-lg"
name="age"
value={this.state.age}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label htmlFor="name">Ville</label>
<input
type="text"
className="form-control form-control-lg"
name="ville"
value={this.state.ville}
onChange={this.onChange}
/>
</div>
<button className="btn btn-primary btn-block">Créez votre Fiche !</button>
</form>
</div>
</div>
{this.renderCard()}
</div>
);
}
}
You are making mistake in setting the items in state on submit. I hope the items should be a array of objects
Please check the below code
onSubmit = (event) => {
event.preventDefault();
this.setState({
nom: '',
age: '',
ville: '',
items: [...this.state.items, {nom:this.state.nom, age:this.state.age, ville: this.state.ville}],
start: 1
});
Related
I have three radio buttons and I need to put the value of the selected one in inputs.reply, just like I did with inputs.name, inputs.email, inputs.phone and inputs.message. How can I do this? I know it's probably a very easy thing to do, but I've been trying for hours and it doesn't work.
import Head from 'next/head'
import React, { useState } from 'react'
export default () => {
const [status, setStatus] = useState({
submitted: false,
submitting: false,
info: { error: false, msg: null }
})
const [inputs, setInputs] = useState({
reply: '',
name: '',
phone: '',
email: '',
message: ''
})
function SubmitButton(){
if (inputs.name && inputs.email && inputs.message) {
return <button type="submit" className="btn-submit" disabled={status.submitting}> {!status.submitting ? !status.submitted ? 'Submit' : 'Submitted' : 'Submitting...'} </button>
} else {
return <button type="submit" className="btn-submit" disabled>Submit</button>
};
};
const handleResponse = (status, msg) => {
if (status === 200) {
setStatus({
submitted: true,
submitting: false,
info: { error: false, msg: msg }
})
setInputs({
reply: '',
name: '',
phone: '',
email: '',
message: ''
})
} else {
setStatus({
info: { error: true, msg: msg }
})
}
}
const handleOnChange = e => {
e.persist()
setInputs(prev => ({
...prev,
[e.target.id]: e.target.value
}))
setStatus({
submitted: false,
submitting: false,
info: { error: false, msg: null }
})
}
const handleOnSubmit = async e => {
e.preventDefault()
setStatus(prevStatus => ({ ...prevStatus, submitting: true }))
const res = await fetch('/api/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(inputs)
})
const text = await res.text()
handleResponse(res.status, text)
}
return (
<div className="contact">
<main>
<div className="content">
<div>
<h2>Get in touch!</h2>
<h3>How can we help you?</h3>
</div>
<form onSubmit={handleOnSubmit}>
<h4>How would you like us to get back to you?</h4>
<div className="form-group form-group-radio">
<div>
<input type="radio" onChange={handleOnChange} value="Phone" name="email-reply" id="reply-phone" />
<label className="radio-label" htmlFor="reply-phone">Phone</label>
</div>
<div>
<input type="radio" onChange={handleOnChange} value="E-mail" name="email-reply" id="reply-email" />
<label className="radio-label" htmlFor="reply-email">E-mail</label>
</div>
<div>
<input type="radio" onChange={handleOnChange} value="No reply needed" name="email-reply" id="no-reply" />
<label className="radio-label" htmlFor="no-reply">No reply needed</label>
</div>
</div>
<div className="form-group">
<input
id="name"
type="text"
name="name"
onChange={handleOnChange}
required
value={inputs.name}
className={inputs.name ? "form-control active" : "form-control"}
/>
<label className="form-label" htmlFor="name">Name</label>
</div>
<div className="form-group">
<input
id="email"
type="text"
name="email"
onChange={handleOnChange}
required
value={inputs.email}
className={inputs.email ? "form-control active" : "form-control"}
/>
<label className="form-label" htmlFor="email">Email</label>
</div>
<div className="form-group">
<input
id="phone"
type="tel"
name="phone"
onChange={handleOnChange}
required
value={inputs.phone}
className={inputs.phone ? "form-control active" : "form-control"}
/>
<label className="form-label" htmlFor="phone">Phone</label>
</div>
<div className="form-group">
<textarea
id="message"
onChange={handleOnChange}
required
value={inputs.message}
className={inputs.message ? "form-control active" : "form-control"}
/>
<label className="form-label" htmlFor="message">Message</label>
</div>
<SubmitButton />
{status.info.error && (
<div className="message-feedback error">
<p>Error: {status.info.msg}</p>
</div>
)}
{!status.info.error && status.info.msg && (
<div className="message-feedback success">
<p>Thanks for messaging us!</p>
<p>We'll get back to you soon.</p>
</div>
)}
</form>
</div>
</main>
</div>
)
}
Thank you.
Remove the id attribute from all of the <input type="radio" /> and instead add a name="reply" to all of them.
Now update handleOnChange, specifically this part
setInputs(prev => ({
...prev,
[e.target.id || e.target.name]: e.target.value
}))
You can update the handleOnChange method to check for the type of the target event and if its a radio button, you can update the radio state, otherwise use the dynamic key to update the state.
const handleOnChange = (e) => {
e.persist();
const key = e.target.type === "radio" ? "reply" : e.target.id;
setInputs((prev) => ({
...prev,
[key]: e.target.value
}));
setStatus({
submitted: false,
submitting: false,
info: { error: false, msg: null }
});
};
<div>
<label>Last Name</label>
<input
type="text"
name="lastName"
defaultValue={userData.lastName}
onChange={(ev) => this.setState({ lastName: ev.target.value })}
/>
</div>
I have some input fields on the screen.When the page loads first time , I am displaying readonly values from the redux store.On click of edit button , I want fields to become editable with the existing values.( i have state which corresponds to each field of the form).DefaultValue is from redux store .but onClick of save of new fields , I am only getting vlaues for fields which I have modified ,otherfields coming as blank.Any help pls?
/* eslint-disable react/destructuring-assignment */
/* eslint-disable react/forbid-prop-types */
/* eslint-disable no-nested-ternary */
import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { eventsActions } from '../../store/actions/index';
class UserAccount extends Component {
//console.log(this.props);
constructor(props) {
console.log('props --- ', props.userData);
super();
this.state = {
username: props.userData.username,
firstName: props.userData.firstName,
lastName: props.userData.lastName,
// profilePic: '',
email: props.userData.email,
addressUnit: props.userData.addressUnit,
addressStreet: props.userData.addressStreet,
addressCity: props.userData.addressCity,
addressZip: props.userData.addressZIP,
addressState: props.userData.addressState,
isEditing: false,
};
this.toggleEdit = this.toggleEdit.bind(this);
}
componentDidMount() {
const { loadUserDetails } = this.props;
loadUserDetails();
}
toggleEdit() {
console.log('toggleEdit is called here ----');
this.setState({ isEditing: !this.state.isEditing });
}
handleChange = (event) => {
console.log('event ---- ', event);
this.setState({ [event.target.name]: event.target.value });
};
updateUser = (e) => {
console.log('updateUser is called ---');
e.preventDefault();
const {
username,
firstName,
lastName,
email,
addressUnit,
addressStreet,
addressCity,
addressZip,
addressState,
} = this.state;
const { editUser } = this.props;
console.log('for updating user --- ', this.state);
editUser(this.state);
};
render() {
const { userData } = this.props;
const {
username,
firstName,
lastName,
email,
addressUnit,
addressStreet,
addressCity,
addressZip,
addressState,
isEditing,
} = this.state;
console.log('userData --- ', userData);
console.log('isEditing ---- ', isEditing);
return (
<div>
{isEditing ? (
<div>
<div>
<label>First Name</label>
<input
type="text"
name="firstName"
// ref={firstName}
value={firstName}
onChange={this.handleChange}
/>
</div>
<div>
<label>Last Name</label>
<input
type="text"
name="lastName"
defaultValue={userData.lastName}
onChange={(ev) => this.setState({ lastName: ev.target.value })}
/>
</div>
<div>
<label>Email</label>
<input
type="text"
name="email"
value={userData.email}
onChange={(ev) => this.setState({ email: ev.target.value })}
/>
</div>
<div>
<label>UserName</label>
<input
type="text"
name="username"
value={userData.username}
onChange={(ev) => this.setState({ username: ev.target.value })}
/>
</div>
<div>
<label>Address Unit</label>
<input
type="text"
name="addressUnit"
value={userData.addressUnit}
onChange={(ev) =>
this.setState({ addressUnit: ev.target.value })
}
/>
</div>
<div>
<label>Address Street</label>
<input
type="text"
name="addressStreet"
value={userData.addressStreet}
onChange={(ev) =>
this.setState({ addressStreet: ev.target.value })
}
/>
</div>
<div>
<label>Address City</label>
<input
type="text"
name="addressCity"
value={userData.addressCity}
onChange={(ev) =>
this.setState({ addressCity: ev.target.value })
}
/>
</div>
<div>
<label>Address State</label>
<input
type="text"
name="addressState"
value={userData.addressState}
onChange={(ev) =>
this.setState({ addressState: ev.target.value })
}
/>
</div>
<div>
<label>Address Zip</label>
<input
type="text"
name="addressZip"
value={userData.addressZIP}
onChange={(ev) =>
this.setState({ addressZip: ev.target.value })
}
/>
</div>
<button type="submit" onClick={this.updateUser}>
Save
</button>
</div>
) : (
<div>
<form>
<div>
<label>First Name:</label>
<label> {userData.firstName}</label>
</div>
<div>
<label>Last Name:</label>
<label> {userData.lastName}</label>
</div>
<div>
<label>Email:</label>
<label> {userData.email}</label>
</div>
<div>
<label>UserName:</label>
<label> {userData.username}</label>
</div>
<div>
<label>Address Unit:</label>
<label> {userData.addressUnit}</label>
</div>
<div>
<label>Address Street:</label>
<label> {userData.addressStreet}</label>
</div>
<div>
<label>Address City:</label>
<label> {userData.addressCity}</label>
</div>
<div>
<label>Address State:</label>
<label> {userData.addressState}</label>
</div>
<div>
<label>Address Zip:</label>
<label> {userData.addressZIP}</label>
</div>
<button type="submit" onClick={this.toggleEdit}>
edit
</button>
</form>
</div>
)}
</div>
);
}
}
const mapStateToProps = (state) => {
console.log('state in UserProfile in mapStatetoProps --- ', state);
return { userData: state.events.user };
};
const mapDispatchToProps = (dispatch) => {
return {
loadUserDetails: (userId) => {
console.log('disptach is called for loadUserDetails --');
dispatch(eventsActions.fetchUserDetails(userId));
},
};
};
UserAccount.propTypes = {
loadUserDetails: PropTypes.func.isRequired,
userData: PropTypes.object.isRequired,
};
export default connect(mapStateToProps, mapDispatchToProps)(UserAccount);
You could e.g. initialize your state with values from redux store.
state = {
lastName: this.props.userData.lastName,
firstName: this.props.userData.lastName,
}; // and so on
Then, even if not modified, state will store the correct data.
Note: Remember to add value prop to the input:
<input onChange={} value={this.state.lastName} />
If your data comes from async request:
componentDidUpdate(prevProps) {
if (!prevProps.userData && this.props.userData){
this.setState({ firstName: this.props.userData.firstName });
}
}
i am trying to create an accounting page wherein I try to add percentage and net to get the get value as well as the total value however I don't know how to implement a function without a button I don't have any examples to go through as well if anyone can help me that would be really grateful
the code is as follows
import React, { Component } from 'react';
import { connect } from "react-redux";
import { getData } from "../actions/company"
import "./css/InvoiceAdd.css"
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import "./css/Togglebox.css"
export class InvoiceSales extends Component {
constructor(props) {
super(props);
this.state = {
Invoice_Date: '',
company_name: '',
GSTIN: '',
invoice_no: '',
percentage: 0,
net: 0,
igst: 0,
cgst: 0,
sgst: 0,
total_invoice: 0,
};
console.log(this.state);
this.onChange = this.onChange.bind(this);
this.onCreate = this.onCreate.bind(this);
this.handlenum1Change = this.handlenum1Change.bind(this);
this.handlenum2Change = this.handlenum2Change.bind(this);
}
componentDidMount() {
document.body.classList.add("background-black");
}
componentDidMount() {
this.props.getData();
}
componentWillUnmount() {
document.body.classList.remove("background-black");
}
onChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
handlenum1Change = evt => {
console.log(evt.target.value);
this.setState({percentage:Number(evt.target.value) });
}
handlenum2Change = evt => {
console.log(evt.target.value);
this.setState({net:Number(evt.target.value) });
};
onCreate(e) {
e.preventDefault();
let Invoice = {
Invoice_Date: this.state.Invoice_Date,
company_name: this.state.company_name,
GSTIN: this.state.GSTIN,
invoice_no: this.state.invoice_no,
percentage: this.state.percentage,
net: this.state.net,
igst: this.state.igst,
sgst: this.state.sgst,
total_invoice: this.state.total_invoice
};
console.log(Invoice);
this.props.postData(Invoice);
this.setState({
Invoice_Date: '',
company_name: '',
GSTIN: '',
invoice_no: '',
percentage: 0,
net: 0,
igst: 0,
cgst: '',
sgst: '',
total_invoice: ''
});
}
render() {
return (
<div classname="masterfile-add" >
<form className="masterfileadd-form">
<p><label className="masterfileadd-text">
Invoice Date :
<DatePicker dateFormat="dd-MM-yyyy" selected={this.state.date} onChange={this.handleDateChange} className="itextbox1" />
</label>
</p>
<label className="masterfileadd-text">
Company Name:
< select value={this.state.company} onchange={this.onChange} name="company_name" className="itextbox2">
{this.props.company.map(company => {
return <option value={company.company_name}>{company.company_name}</option>
})}
</select>
</label>
<p><label className="masterfileadd-text">
GSTIN :
<input type="text" name="GSTIN" value={this.state.GSTIN} onChange={this.onChange} className="itextbox3"></input>
</label>
</p>
<p><label className="masterfileadd-text">
Invoice No :
<input type="text" name="invoice_no" value={this.state.invoice_no} onChange={this.onChange} className="itextbox4"></input>
</label>
</p>
<p> <label className="masterfileadd-text">
Percentage:
<input type="number" step="0.1" name="percentage" value={this.state.percentage} handlenum1Change={this.handlenum1Change} className="itextbox5"></input>
</label>
</p>
<p><label className="masterfileadd-text">
NET :
<input type="number" name="net" value={this.state.net} handlenum2Change={this.handlenum2Change} className="itextbox6"></input>
</label>
</p>
<p><label className="masterfileadd-select">
IGST :
<input type="text" value={this.state.igst} readOnly />
</label>
</p>
<p><label className="masterfileadd-select">
CGST :
<input type="text" name="cgst" value={this.state.opening_balance} onChange={this.onChange} className="itextbox8"></input>
</label>
</p>
<p><label className="masterfileadd-select">
SGST:
<input type="text" name="sgst" value={this.state.opening_balance} onChange={this.onChange} className="itextbox9"></input>
</label>
</p>
<p><label className="masterfileadd-select">
Total Invoice :
<input type="text" name="total_invoice" value={this.state.head_of_account} onChange={this.onChange} className="itextbox10"></input>
</label>
</p>
<p className="iButton" ><input type="submit" value="Submit" onChange={this.onChange} onClick={this.onCreate} className="mButtonAdd" />
</p>
</form>
</div>
)
}
}
const mapStateToProps = state => ({
company: state.companyReducer.company,
error: state.journalReducer.error
});
export default connect(
mapStateToProps,
{ getData }
)(InvoiceSales)
Hı ,
in onchange event
if(event.target.name =="input1" || event.target.name=="input2")
{
this.setState({result: Number(this.state.input1)+ Number(this.state.input2)})
}
try something like this. input1 and input2 are your textboxes. And be sure textbox value is number .may be you can check.
I need to create multiple medicine objects here. I just want to change state into array of objects. How to do that effectively? Also, want to implement controlled component for multiple medicine objects form.
Here's my component for a single medicine object:
export class MedicineForm extends Component {
state = {
medicine_name: "",
details: ""
}
static propTypes = {
postMedicine: PropTypes.func.isRequired
}
onChange = e => {
this.setState({
[e.target.name]: e.target.value
})
}
onSubmit = e => {
e.preventDefault()
const { medicine_name, details } = this.state
const medicine = { medicine_name, details }
this.props.postMedicine(medicine)
// Following code works as desired. Need to change state in this JSON Array of objects.
// this.props.postMedicine([
// {
// "id": 14,
// "medicine_name": "many5",
// "details": "sdknas"
// },
// {
// "id": 15,
// "medicine_name": "many6",
// "details": "sdknas"
// }
// ])
}
render() {
const { medicine_name, details } = this.state
return (
<Fragment>
<h1>Add Medicine</h1>
<form className="card card-body" onSubmit={this.onSubmit}>
<div className="form-row">
<div className="form-group col-md-3">
<label htmlFor="medicine_name">Medicine Name</label>
<input type="text" className="form-control" name="medicine_name" id="medicine_name" placeholder="Medicine Name" value={medicine_name} onChange={this.onChange} />
</div>
<div className="form-group col-md-3">
<label htmlFor="details">Details</label>
<input type="text" className="form-control" name="details" id="details" placeholder="Details" value={details} onChange={this.onChange} />
</div>
<div className="form-group mx-auto mt-3">
<button type="submit" className="btn btn-primary btn-lg">
Submit
</button>
</div>
</div>
</form>
</Fragment>
)
}
}
In actions, I have added following postMedicine method:
export const postMedicine = (medicine) => dispatch => {
axios.post('./api/medicine/', medicine)
.then(res => {
dispatch({
type: POST_MEDICINE,
payload: res.data
})
})
.catch(err => console.log(err))
}
//this is one row, add multiple rows as needed
state = {
medicines: [{medicine_name: "",
details: ""
}]
}
//other code
onChange = (e, i) => {
const newMedicines = this.state.medicines;
newMedicines[i] = {[e.target.name]: e.target.value, ...newMedicines[i]}
this.setState({medicines: newMedicines})
}
onSubmit = e => {
e.preventDefault()
const { medicine_name, details } = this.state
const medicine = { medicine_name, details }
this.props.postMedicine(medicine)
// Following code works as desired. Need to change state in this JSON Array of objects.
// this.props.postMedicine(this.state.medicines)
}
<form className="card card-body" onSubmit={this.onSubmit}>
{this.state.medicines.map((m, i) => (<div className="form-row">
<div className="form-group col-md-3">
<label htmlFor="medicine_name">Medicine Name</label>
<input type="text" className="form-control" name="medicine_name" id="medicine_name" placeholder="Medicine Name" value={m.medicine_name} onChange={(e) => this.onChange(e, i)} />
</div>
<div className="form-group col-md-3">
<label htmlFor="details">Details</label>
<input type="text" className="form-control" name="details" id="details" placeholder="Details" value={m.details} onChange={(e) => this.onChange(e, i)} />
</div>
<div className="form-group mx-auto mt-3">
<button type="submit" className="btn btn-primary btn-lg">
Submit
</button>
</div>
</div>))}
</form>
Form component has two parameter (aka props).
first one is item, wich determines how many form do you need.
1 form means you have group of two inputs [medicine_name,details]
2 = 4 input (2 group)
...etc
and second props is function named formHandler.
wich lifting data from child
export class MedicineForm extends Component {
state = {
medicine: [],
};
static propTypes = {
postMedicine: PropTypes.func.isRequired,
};
formHandler = (value) => {
this.setState({ medicine: value });
};
onSubmit = (e) => {
e.preventDefault();
this.props.postMedicine(this.medicine);
};
render() {
return (
<>
<h1>Add Medicine</h1>
{JSON.stringify(this.state.medicine)}
<form className="card card-body" onSubmit={this.onSubmit}>
<Form item="4" formHandler={this.formHandler} />
<div className="form-group mx-auto mt-3">
<button type="submit" className="btn btn-primary btn-lg">
Submit
</button>
</div>
</form>
</>
);
}
}
Form Component
class Form extends Component {
constructor(props) {
super(props);
}
state = {
medicine: [...Array(+this.props.item)].map((_, idx) => ({
id: idx + 1,
medicine_name: "",
details: "",
})),
};
static propTypes = {
item: PropTypes.string,
formHandler: PropTypes.func,
};
onChange = ({ target: { id, name, value } }) => {
this.setState((prevState) => {
const medicine = prevState.medicine.map((item) =>
item.id === Number(id) ? { ...item, [name]: value } : item
);
this.props.formHandler(
medicine.filter((item) => item["medicine_name"] || item["details"])
);
return {
medicine,
};
});
};
render() {
return (
<div className="form-row">
{this.state.medicine.map((item, id) => (
<div key={item.id}>
<div className="form-group col-md-3">
<label htmlFor="medicine_name">Medicine Name</label>
<input
type="text"
className="form-control"
name="medicine_name"
id={item.id}
value={item.medicine_name}
placeholder="Medicine Name"
onChange={this.onChange}
/>
</div>
<div className="form-group col-md-3">
<label htmlFor="details">Details</label>
<input
type="text"
className="form-control"
name="details"
id={item.id}
value={item.details}
placeholder="Details"
onChange={this.onChange}
/>
</div>
</div>
))}
</div>
);
}
}
there is check if object has some value then lifting data.
you can change logic optional
medicine.filter((item) => item["medicine_name"] || item["details"])
You could do something like this in redux store:
[
{ id: 1, medicineName: '', details: '' },
{ id: 2, medicineName: '', details: '' },
...
]
And to make your input fields controlled just handle the state in the component.
I have list of input tags in my react app. I want to get the value of all inputs when I click on submit button.
I can get the value of one input, but not able to get all the values in one go.
keys.map(i => <Input fullWidth defaultValue={i} />)
<Button>Submit</Button>
get the list of values
Sample application for multiple inputs
const App = () => {
const [people, setPeople] = React.useState([
{ firstName: "Herry", lastName: "Sejal" },
{ firstName: "John", lastName: "Siri" },
{ firstName: "Bukky", lastName: "Sera" }
]);
const [person, setPerson] = React.useState({ firstName: "", lastName: "" });
const onChange = e => {
setPerson({ ...person, [e.target.name]: e.target.value });
};
const onSubmit = e => {
e.preventDefault();
const newVal = [...people, person];
setPeople(newVal);
setPerson({ firstName: "", lastName: "" });
};
return (
<div className="container">
<div className="row">
<div className="col">
<h2>Add a person: </h2>
<hr />
<form onSubmit={onSubmit}>
<div className="form-group">
<input
type="text"
className="form-control"
name="firstName"
placeholder="First Name.."
value={person.firstName}
onChange={onChange}
/>
</div>
<div className="form-group">
<input
type="text"
className="form-control"
name="lastName"
placeholder="Last Name.."
value={person.lastName}
onChange={onChange}
/>
</div>
<button className="btn btn-success" type="submit">
Add person
</button>
</form>
</div>
<div className="col">
<h2>People: </h2>
<hr />
{people.map(p => (
<div key={Math.random() * 1000000000}>
<p>
{p.firstName} {p.lastName}
</p>
</div>
))}
</div>
</div>
</div>
);
};