how to edit a textfield values in reactjs - reactjs

Here i add my sample code.i have a static values getting from state now i want to change this values
render() {
console.log(this.props.selectedVal);
var name,
gender,
city = "";
this.props.data.map((row, index) => {
// console.log(index);
if (this.props.selectedVal === index) {
gender = row[0];
name = row[1];
city = row[2];
}
return [];
});
return (
<Dialog
open={this.props.open}
onClose={this.handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<h1>Edit User</h1>
<DialogContent>
<DialogContentText id="alert-dialog-description" />
<Formik
initialValues={{ name: "", gender: "", city: "" }}
onSubmit={values => console.log(values)}
>
{props => (
<form>
<TextField margin="dense" id="name" label="Name" value={name} />
<br />
<TextField
margin="dense"
id="gender"
label="Gender"
value={gender}
/>
<br />
<TextField margin="dense" label="City" value={city} />
</form>
)}
</Formik>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color="primary">
RESET
</Button>
<Button onClick={this.handleClose} color="primary" autoFocus>
SUBMIT
</Button>
</DialogActions>
</Dialog>
);
}
I am getting the values from the table row.Now i want to change these values using formik. How can I edit these values

Add a onChange listener in your textfield and map the value to a state variable:
textChange(e) {
const value = e.target.value
this.setState({ value })
}
render() {
return (
<TextField value={this.state.value} onChange={this.textChange} .. />
)
}
If you want to handle more values from different textfields using one method try something like this:
textChange(e) {
const id = e.target.id
const value = e.target.value
this.setState({ [id]: value })
}
render() {
return (
<TextField id="gender" value={this.state.gender} onChange={this.textChange} .. />
<TextField id="dense" value={this.state.dense} onChange={this.textChange} .. />
)
}

It seems like you get data with props from parent component. And, if I get it wright, question is how to change state of parent component? You need to add to props function binded to parent`s context and use setState there.

Related

Using React Hook Form with other component

I want to create dynamic form with react-hook-form.
Below is my code.
I want to create a dialog for entering a detailed profile in a separate component and use it in MainForm.
I can display the DetailForm, but the values entered in it are not reflected.
Data on the DetailForm component is not included when submitting.
Any guidance on how to do this would be greatly appreciated.
MainForm
import React from 'react';
import {
useForm,
Controller,
useFieldArray
} from 'react-hook-form';
import {
Button,
TextField,
List,
ListItem,
IconButton,
} from '#material-ui/core';
import DetailForm from '#components/DetailForm'
import AddCircleOutlineIcon from '#material-ui/icons/AddCircleOutline';
function MainForm(props:any) {
const { control, handleSubmit, getValues } = useForm({
mode: 'onBlur',
defaultValues: {
profiles: [
{
firstName: '',
lastName: '',
email: '',
phone: ''
}
]
}
});
const { fields, append, remove } = useFieldArray({
control,
name: 'profiles',
});
const onSubmit = () => {
const data = getValues();
console.log('data: ', data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<List>
fields.map((item, index) => {
return (
<ListItem>
<Controller
name={`profiles.${index}.firstName`}
control={control}
render={({field}) =>
<TextField
{ ...field }
label="First Name"
/>
}
/>
<Controller
name={`profiles.${index}.lastName`}
control={control}
render={({field}) =>
<TextField
{ ...field }
label="Last Name"
/>
}
/>
<DetailForm index={index} />
</ListItem>
)
})
</List>
<IconButton onClick={() => append({})}>
<AddCircleOutlineIcon />
</IconButton>
<Button
type='submit'
>
SAVE
</Button>
</form>
)
}
DetailForm
import React from 'react';
import {
Button,
TextField,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
} from '#material-ui/core';
export default function DetailForm(props: any) {
const [dialogState, setDialogState] = React.useState<boolean>(false);
const handleOpen = () => {
setDialogState(true);
};
const handleClose = () => {
setDialogState(false);
};
return (
<>
<Button
onClick={handleOpen}
>
Set Detail Profile
</Button>
<Dialog open={dialogState}>
<DialogTitle>Detail Profile</DialogTitle>
<DialogContent>
<TextField
name={`profiles.${props.index}.email`}
label="Email Address"
/>
<TextField
name={`profiles.${props.index}.phone`}
label="Phone Number"
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>
Cancel
</Button>
<Button onClick={handleClose}>
Add
</Button>
</DialogActions>
</Dialog>
</>
)
}
You have to register those fields inside your <Dialog /> component - just pass control to it. It's also important to set an inline defaultValue when using <Controller /> and useFieldArray. From the docs:
inline defaultValue is required when working with useFieldArray by integrating with the value from fields object.
One other minor thing: You should also pass the complete fieldId to your <Dialog /> component instead of just passing the index. This way it would be easier to change the fieldId in one place instead of editing all fields in your <Dialog /> component.
MainForm
<ListItem key={item.id}>
<Controller
name={`profiles.${index}.firstName`}
control={control}
defaultValue=""
render={({ field }) => (
<TextField {...field} label="First Name" />
)}
/>
<Controller
name={`profiles.${index}.lastName`}
control={control}
defaultValue=""
render={({ field }) => (
<TextField {...field} label="Last Name" />
)}
/>
<DetailForm control={control} fieldId={`profiles.${index}`} />
</ListItem>
DetailForm
export default function DetailForm({ control, fieldId }) {
const [dialogState, setDialogState] = React.useState(false);
const handleOpen = () => {
setDialogState(true);
};
const handleClose = () => {
setDialogState(false);
};
return (
<>
<Button onClick={handleOpen}>Set Detail Profile</Button>
<Dialog open={dialogState}>
<DialogTitle>Detail Profile</DialogTitle>
<DialogContent>
<Controller
name={`${fieldId}.email`}
control={control}
defaultValue=""
render={({ field }) => (
<TextField {...field} label="Email Address" />
)}
/>
<Controller
name={`${fieldId}.phone`}
control={control}
defaultValue=""
render={({ field }) => (
<TextField {...field} label="Phone Number" />
)}
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={handleClose}>Add</Button>
</DialogActions>
</Dialog>
</>
);
}

Passing a function and parameters with onclick in react

i am trying to create a dynamic form where a user can enter the details of a guest list. I also want to be on every row a button called "email" where the user can click on it and an automatically generated email would be sent to the guest on that row. i have created the dynamic form and i have a fun a function that sends emails using (mailjs) what i cant do is pass the details of that particular row to the onlcick function so the email is sent to the right guest
my form code :
const useStyles = makeStyles((theme)=>({
root:{
"& .MuiTextField-root":{
margin: theme.spacing(1),
}
},
button:{
margin: theme.spacing(1)
}
}))
function Guests () {
const classes=useStyles()
const [inputFields, setInputField] = useState([
{firstName: "", lastName:"", email:"", rsvp:"", menue:""},
])
const handleSubmit =(e) =>{
e.preventDefault();
console.log("input fields", inputFields)
}
const handleChangeInput = (index, event) =>{
console.log(index, event.target.name)
const values =[...inputFields];
values[index][event.target.name] = event.target.value
setInputField(values)
}
const handleAddField = () =>{
setInputField([...inputFields,{firstName: "", lastName:"", email:"", rsvp:"", menue:""}])
}
const handleRemoveField =(index) =>{
const values = [...inputFields]
values.splice(index, 1)
setInputField(values)
}
return (
<Container>
<h1> Your Guest List</h1>
<form className={classes.root} onSubmit={handleSubmit}>
{inputFields.map((inputField, index)=>(
<div key={index}>
<TextField
name="firstName"
label="First Name"
value={inputField.firstName}
onChange={event => handleChangeInput(index, event)}
/>
<TextField
name="lastName"
label="Last Name"
value={inputField.lastName}
onChange={event => handleChangeInput(index, event)}
/>
<TextField
name="email"
label="Email"
value={inputField.email}
onChange={event => handleChangeInput(index, event)}
/>
<TextField
name="rsvp"
label="RSVP"
value={inputField.rsvp}
onChange={event => handleChangeInput(index, event)}
/>
<TextField
name="menue"
label="Menu Choice"
value={inputField.menue}
onChange={event => handleChangeInput(index, event)}
/>
<Button className={classes.button}
vareient="contained"
color="secondary"
>Send email</Button>
<IconButton
onClick={()=> handleRemoveField(index)}>
<RemoveIcon />
</IconButton>
<IconButton
onClick={() => handleAddField()}>
<AddIcon />
</IconButton>
</div>
))}
<Button
className={classes.button}
vareient="contained"
color="secondary"
type="submit"
onClick={handleSubmit}
endIcon={<Icon>save</Icon>}>
Save Guest List
</Button>
</form>
</Container>
)
}
export default Guests
my email function is :
function sendEmail (event){
event.preventDefault();
emailjs.sendForm(service,template,event.target,hero).then(res=>{
console.log(res)
alert("email sent thank you");
}).catch(err=> console.log(err));
}
Many thanks for you help

How to save typed values inside the initialValues of Formik data?

I use Formik to create the form :
const initialValues = {
groupName: '',
description: '',
testGroup: 0
};
return (
<Formik initialValues={initialValues} >
{(formik) => {
const { setValues } = formik;
const onRadioGroupetestChange = (input) => {
setValues({
...initialValues,
testGroup: Number(input)
});
};
return (
<Form>
<FormikControl
control="input"
label={_getText("group.name")}
name="groupName"
placeholder={_getText("placeholder.group.name")}
/>
<FormikControl
control="textarea"
label={_getText("description")}
name="description"
placeholder={_getText("placeholder.group.descr")}
/>
<FormikControl
formik={formik}
control="radio"
onChange={onRadioGroupetestChange}
initialValue={initialValues.testGroup}
name="testGroup"
label={_getText('group.test')}
options={radioDataGroupTest}
/>
<Flex
flexWidth={1}
alignItems="center"
justifyContent="center"
margin="2rem 0 0 0"
>
<Flex margin="0 0.8rem 0 0">
<Button
variant="line"
text="Cancel"
type="reset"
onClick={closeModal}
/>
</Flex>
<Flex margin="0 0 0 0.8rem">
<Button text="Submit" type="submit" />
</Flex>
</Flex>
</Form>
);
}}
</Formik>
The FormikControl component with props "testGroup" renders two radio buttons.
At runtime when I click the unchecked button of the radio button then all the fields of the form are cleared. So how to save the data I entered in the components groupName and description ?
That's why you are resetting form with:
setValues({
...initialValues,
testGroup: Number(input)
});
Try setFieldValue instead, or use values instead of initialFormValues.

formik fields are not getting value

I'm using Formik in my React and redux project, but Formik fields are not getting value and onChange field function not working!
this form is for editing a customer. I'm using Formik in another part of project and i don't have a problem. I don't know what to do?
<Formik
initialValues={props.selectedCustomer.id ? props.selectedCustomer : emptyCustomer}
validationSchema={customerValidationSchema}
onSubmit={async (values: ICustomer, actions: FormikActions<any>) => {
console.log(values)
try {
await postCustomer(values)
props.selectedCustomer.id ? enqueueSnackbar('success') : enqueueSnackbar('fail')
actions.resetForm()
getCustomers(pageNum, pageSize)
setAddDialog(false)
}
catch (error) {
enqueueSnackbar(error, { variant: 'default' })
}
}}
>
{() => (
<Form id="addCustomerForm">
<div id="addCustomerDiv" className={clsx({
[classes.noDisplay]: !addDialog
})}>
<Grid style={{marginRight: '0.5rem'}} container spacing={5}>
<Grid item xs={2}>
<Field
name="firstName"
render={({ field, form }: FieldProps<ICustomer>) => (
<TextField
margin="dense"
id="firstName"
label="firstName"
fullWidth
{...field}
error={form.errors.firstName && form.touched.firstName ? true : false}
/>
)}
/>
</Grid>
<Button
type='submit'
form="addCustomerForm"
color="primary"
variant="contained"
style={{marginTop: '3rem'}}
className={clsx({
[classes.noDisplay]: !addDialog
})}
>
submit
</Button>
</Grid>
</Grid>
</div>
</Form>
)}
</Formik>
what is the problem?
I added enableReinitialize in Formik component and it worked.

how to edit a form in react using formik

var fname,
gender,
city = "";
this.props.data.map((row, index) => {
// console.log(index);
if (this.props.selectedVal === index) {
gender = row[0];
fname = row[1];
city = row[2];
}
return [];
});
return (
<div>
<Dialog
open={this.props.open}
onClose={this.handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<h1>Edit User</h1>
<DialogContent>
<DialogContentText id="alert-dialog-description" />
<form onSubmit={handleSubmit}>
<TextField
type="text"
margin="dense"
id="firstname"
label="Name"
onChange={handleChange}
value={fname}
{...props}
/>
<br />
<TextField
type="text"
margin="dense"
id="gender"
label="gender"
onChange={handleChange}
value={gender}
{...props}
/>
<br />
<TextField
type="text"
margin="dense"
id="city"
label="city"
onChange={handleChange}
value={city}
{...props}
/>
</form>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color="primary">
RESET
</Button>
<Button onClick={this.handleClose} color="primary" autoFocus>
SUBMIT
</Button>
</DialogActions>
</Dialog>
</div>
);
};
render() {
return (
<div align="center">
<Formik
initialValues={{
name: this.props.fname,
gender: this.props.gender,
city: this.props.city
}}
onSubmit={initialValues => console.log("values" + initialValues.name)}
render={this.form}
/>
</div>
);
}
}
Here i am getting the values from table while click on a specific row. I'm getting these values in a dialog using formik. Now i want to edit this formik form. I faced a problem. These values are not edited. How to edit these readonly values.
I added my codesandbox link codesandbox
The way you are doing things is not correct. Some of the functions which you are using never exist.
Here is the working demo of your code Codesandbox demo
Please take a look at the code and understand how it is transformed between two components and feel free to ask me if you have any queries/get stuck understanding the code.

Resources