Formik reset button doesn't clear the form - javascript

I have the following:
<Formik initialValues={{}} onSubmit={data => console.log(data)}>
<Form className="h-full">
<FieldsWrapper className="hide-scrolling-bar">
{filters?.map(filter => (
<FiltersGroup
name={filter.label}
filters={filter.children}
/>
))}
</FieldsWrapper>
<ButtonsWrapper>
<Button type="submit" text="apply all" isPrimary />
<Button
type="reset"
text="clear all"
isWishList
isPrimary={false}
/>
</ButtonsWrapper>
</Form>
</Formik>
however the reset button doesn't clear the form
FILTERGROUP COMPONENT
...
const FiltersGroup = ({filters, name}) => {
const Checkbox = ({
field: {name, value, onChange, onBlur},
id,
label,
className,
...props
}) => {
return (
<div className="flex">
<input
name={name}
id={id}
type="checkbox"
value={label}
onChange={onChange}
onBlur={onBlur}
className="hidden"
{...props}
/>
<SizeLabel htmlFor={id}>{label}</SizeLabel>
</div>
)
}
return (
<div className="mb-10">
<GroupLabel>{name}</GroupLabel>
<div className="flex flex-wrap">
{filters?.map(filter => (
<Field
component={Checkbox}
name={name}
id={`id-${filter}`}
label={filter}
/>
))}
</div>
</div>
)
}
export default FiltersGroup

Once you have the fields into a Formik tag then:
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
validateOnBlur={false}
validateOnChange={false}
onSubmit={async (values, { resetForm }) => {
await onSubmit(values)
resetForm()
}}
>
....
When you click Submit button it reset automatically
EDIT:
Example:
const initialValues = {
name: ''
}
<Formik
initialValues={initialValues}>
{formik => {
console.log('formik props', formik)
return (
<div>
<h1>EDIT USER</h1>
<Form>
<Field name="name" type="text" />
<br/><br/><br/>
<div>
<button type="reset" onClick={()=>formik.resetForm()}>
Reset All
</button>
</div>
</Form>
</div >
)
}}
</Formik >
In your case:
<Formik initialValues={{}} onSubmit={data => console.log(data)}>
{formik => {
<Form className="h-full">
<FieldsWrapper className="hide-scrolling-bar">
{filters?.map(filter => (
<FiltersGroup
name={filter.label}
filters={filter.children}
/>
))}
</FieldsWrapper>
<ButtonsWrapper>
<Button type="submit" text="apply all" isPrimary />
<Button
type="reset"
text="clear all"
isWishList
isPrimary={false}
onClick={()=>formik.resetForm()}
/>
</ButtonsWrapper>
</Form>
}}
</Formik>

Related

I have this child component where you can submit a form, however, e.preventDefault() does not work

From the parent component. There are other forms, hence, there is a conditional form where it will used the child component's form.
A user may click the button to show the form from the child component.
const [isTrue, setIsTrue] = useState(false);
<ButtonForm onClick={() => setIsTrue(true)}>
Click for the Form
</ButtonForm>
{isTrue == true ? (
<Form
data={entryData}
items={items}
names={names}
/>
) : (
></>
)}
This is the child component. The problem here is that, everytime I'll submit it, it will reload the page:
const Form = ({ entryData, items, names }) => {
const handleSubmit = (e) => {
e.preventDefault();
try {
console.log(" saved");
} catch (err) {
console.log(err);
}
};
return (
<>
<form onSubmit={handleSubmit}>
//some codes here
<Grid item>
<TextField
type="text"
label="Item Number"
variant="outlined"
fullWidth
required
/>
</Grid>
//some codes here
<Grid item>
<Button type="submit" fullWidth>
Submit
</Button>
</Grid>
</form>
<br /> <br />
</>
);
};
export default Form;
This is the sample parent component: most where just forms
<div className="App">
<Card className={classes.root}>
<CardContent>
{users &&
users.map((user) => (
<li style={{ listStyle: "none" }}>
<Button onClick={() => setIsTrue(true)}>
Click for the Form
</Button>
{//if user condition is true here == true ? (
<div>
//form here with the textfields
</div>
) : (
<div>
//form here with the textfields
</div>
)}
</li>
))}
</>
{isTrue == true ? (
<Form
data={entryData}
items={items}
names={names}
/>
) : (
></>
)}
</CardContent>
</Card>
</div>
// on click trigger submit in first and second forms
<form>
<form>
<button type="submit" />
</form>
<button type="submit" />
</form>;
//solution
<form onSubmit={(e) => e.preventDefault()}>
<form onSubmit={(e) => e.preventDefault()}>
<button type="submit" /> // on click trigger submit in first and second form
</form>
<button type="submit" />
</form>;

None of the Tabs' children match with `[object Object]`. You can provide one of the following values: 0, 1

I am building header using material UI Tab Component but I see below error:
index.js:2178 Material-UI: The value provided to the Tabs component is invalid.
None of the Tabs' children match with [object Object].
You can provide one of the following values: 0, 1.
I tried console.log the newValue to see what value it is getting and I can see 0 and 1 while navigating through tabs.
Note : Removed Some Code for better visibility
Here is my component:
const Header = (props) => {
const { classes } = props;
const [value, setValue] = useState(0);
const [modalIsOpen, setIsOpen] = React.useState(false);
const openModal = () => {
setIsOpen(true);
};
const closeModal = () => {
setIsOpen(false);
};
const handleTabChange = (event, newValue) => {
console.log(newValue);
setValue({ newValue });
};
return (
<div>
<div className="topnav">
<img src={logo} className="logo" alt="Movies App Logo" />
<div className="topnav-right">
<Button variant="contained" color="default" onClick={openModal}>
Login
</Button>
</div>
<div className="topnav-right">
<Button variant="contained" color="default">
Logout
</Button>
</div>
</div>
<Modal
ariaHideApp={false}
isOpen={modalIsOpen}
onRequestClose={closeModal}
contentLabel="Login"
aria-labelledby="Modal"
aria-describedby="Modal for Login and Registration"
style={customStyles}
>
<Paper className={classes.Paper}>
<CardContent>
<Tabs
className="tabs"
value={value}
onChange={handleTabChange}
centered
>
<Tab label="Login" />
<Tab label="Register" />
</Tabs>
{value === 0 && (
<div>
<FormControl required>
<InputLabel htmlFor="username" className={classes.inputLable}>
Username
</InputLabel>
<Input
className={classes.Input}
id="username"
type="text"
username={username}
onChange={usernameChangeHandler}
/>
<FormHelperText>
<span className="red">required</span>
</FormHelperText>
</FormControl>
<br />
<br />
<FormControl required>
<InputLabel
htmlFor="loginPassword"
className={classes.inputLable}
>
Password
</InputLabel>
<Input
className={classes.Input}
id="loginPassword"
type="password"
password={password}
onChange={passwordChangeHandler}
/>
<FormHelperText>
<span className="red">required</span>
</FormHelperText>
</FormControl>
<br />
<br />
{loggedIn === true && (
<FormControl>
<span className="success-text">Login Successful!</span>
</FormControl>
)}
<br />
<br />
<Button
variant="contained"
color="primary"
onClick={loginHandler}
>
LOGIN
</Button>
</div>
)}
{value === 1 && (
<div>
<h1>something</h2>
</div>
)}
</CardContent>
</Paper>
</Modal>
</div>
);
};
export default withStyles(styles)(Header);
For some reason you enclosed the value in an object (curly braces syntax).
Replace setValue({ newValue }) with setValue(newValue).

redux form - how can i show input before click add button?

I tried this tutorial: https://redux-form.com/6.1.1/examples/fieldarrays/ but I want to show "first name" and "last name" inputs before clicking the "add member" button. I mean, when the page is first opened, the two inputs will already be shown and the user will press the button whenever the user wants to add extra input. how can I do that?
import React from 'react'
import { Field, FieldArray, reduxForm } from 'redux-form'
import validate from './validate'
const renderField = ({ input, label, type, meta: { touched, error } }) => (
<div>
<label>{label}</label>
<div>
<input {...input} type={type} placeholder={label}/>
{touched && error && <span>{error}</span>}
</div>
</div>
)
const renderMembers = ({ fields, meta: { touched, error } }) => (
<ul>
<li>
<button type="button" onClick={() => fields.push({})}>Add Member</button>
{touched && error && <span>{error}</span>}
</li>
{fields.map((member, index) =>
<li key={index}>
<button
type="button"
title="Remove Member"
onClick={() => fields.remove(index)}/>
<h4>Member #{index + 1}</h4>
<Field
name={`${member}.firstName`}
type="text"
component={renderField}
label="First Name"/>
<Field
name={`${member}.lastName`}
type="text"
component={renderField}
label="Last Name"/>
<FieldArray name={`${member}.hobbies`} component={renderHobbies}/>
</li>
)}
</ul>
)
const renderHobbies = ({ fields, meta: { error } }) => (
<ul>
<li>
<button type="button" onClick={() => fields.push()}>Add Hobby</button>
</li>
{fields.map((hobby, index) =>
<li key={index}>
<button
type="button"
title="Remove Hobby"
onClick={() => fields.remove(index)}/>
<Field
name={hobby}
type="text"
component={renderField}
label={`Hobby #${index + 1}`}/>
</li>
)}
{error && <li className="error">{error}</li>}
</ul>
)
const FieldArraysForm = (props) => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form onSubmit={handleSubmit}>
<Field name="clubName" type="text" component={renderField} label="Club Name"/>
<FieldArray name="members" component={renderMembers}/>
<div>
<button type="submit" disabled={submitting}>Submit</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>Clear Values</button>
</div>
</form>
)
}
export default reduxForm({
form: 'fieldArrays', // a unique identifier for this form
validate
})(FieldArraysForm)

React modal window does not show with Hooks

I'm wondering why my modal view is no showing up. I've followed examples from semantic-ui and also from bootstrap but none are working.
I'm not sure to use Hooks as it requires. Or HandleEditRecipe function is not at top level of my component and it does not render ?
I'd like to display a modal view by clicking on this button:
<button onClick={HandleEditRecipe.bind(null, key, data)}>Edit</button>
This is my code :
import { Modal, Button } from 'react-bootstrap'
const RecipeCard = ({
id: key,
recipies,
updateRecipe,
deleteRecipe,
data
}) => {
const [show, setShow] = React.useState(false)
let recipeUpdate = {
name: '',
image: '',
ingredients: '',
instructions: ''
}
const handleShow = () => setShow(true)
function HandleEditRecipe (key, data) {
const handleClose = () => setShow(false)
return (
<>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>
<div className='card'>
<form action='' className='admin-form'>
<input value={data.name} onChange={e => handleChange(e, key)} type='text' name='name' />
<input value={data.image} onChange={e => handleChange(e, key)} type='text' name='image' />
<textarea value={data.ingredients} onChange={e => handleChange(e, key)} name='ingredients' rows='3' />
<textarea value={data.instructions} onChange={e => handleChange(e, key)} name='instructions' rows='15' />
</form>
<button onClick={() => handleValidEdit(key)}>Supprimer</button>
</div>
</Modal.Body>
<Modal.Footer>
<Button variant='secondary' onClick={handleClose}>
Close
</Button>
<Button variant='primary' onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</>
)
}
return (
<div className='card'>
<div className='recipe'>
<h2>{data.name} - {key}</h2>
<Button variant='primary' onClick={handleShow}>
Launch demo modal
</Button>
<button onClick={HandleEditRecipe.bind(null, key, data)}>Edit</button>
<div className='image'>
<img src={requireImage(data.image)} alt={data.name} />
</div>
<ul className='list-ingredients'>
{data.ingredients}
</ul>
<ol className='list-instructions'>
{data.instructions}
</ol>
</div>
</div>
)
}
export default RecipeCard
Thank you !
EDIT SOLUTION:
I finally manage to display modal view with hooks :
const RecipeCard = ({
id: key,
recipies,
updateRecipe,
deleteRecipe,
data
}) => {
const [isOpen, setIsOpen] = React.useState(false)
const showModal = () => {
setIsOpen(true)
}
const hideModal = () => {
setIsOpen(false)
}
return (
<div className='card'>
<div className='recette'>
<h2>{data.name} - {key}</h2>
<button onClick={() => handleDeleteRecipe(key)}>Delete</button>
<div className='image'>
<img src={requireImage(data.image)} alt={data.name} />
</div>
<ul className='liste-ingredients'>
{ingredients}
</ul>
<ol className='liste-instructions'>
{instructions}
</ol>
</div>
<button onClick={showModal}>Edit</button>
<Modal show={isOpen} onHide={hideModal}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>
<div className='card'>
<h1>DIOOO</h1>
<form action='' className='admin-form'>
<input value={data.name} onChange={e => handleChange(e, key)} type='text' name='name' />
<input value={data.image} onChange={e => handleChange(e, key)} type='text' name='image' />
<textarea value={data.ingredients} onChange={e => handleChange(e, key)} name='ingredients' id='' rows='3' />
<textarea value={data.instructions} onChange={e => handleChange(e, key)} name='instructions' id='' rows='15' />
</form>
</div>
</Modal.Body>
<Modal.Footer>
<button onClick={hideModal}>Close</button>
<button>Save</button>
</Modal.Footer>
</Modal>
</div>
)
}
export default RecipeCard

Redux Form Field Arrays-initializing a field array with a specific length

I would like for my form component to start off with a field array with 3 empty fields. Can anyone explain how to initialize it this way?
I'm going off the example provided in the documentation here: https://redux-form.com/7.0.4/examples/fieldarrays/
Here, we can see that originally, we have no fields, and only when we click on the relevant button do we add them, by calling onClick={() => fields.push({})}.
I'd like to start off with three fields and allow the user to add more. Calling fields.push in ComponentDidMount doesn't work. How do I initialize the fields object with a specific length?
FieldArraysForm.js
import React from 'react'
import { Field, FieldArray, reduxForm } from 'redux-form'
import validate from './validate'
const renderField = ({ input, label, type, meta: { touched, error } }) =>
<div>
<label>
{label}
</label>
<div>
<input {...input} type={type} placeholder={label} />
{touched &&
error &&
<span>
{error}
</span>}
</div>
</div>
const renderHobbies = ({ fields, meta: { error } }) =>
<ul>
<li>
<button type="button" onClick={() => fields.push()}>
Add Hobby
</button>
</li>
{fields.map((hobby, index) =>
<li key={index}>
<button
type="button"
title="Remove Hobby"
onClick={() => fields.remove(index)}
/>
<Field
name={hobby}
type="text"
component={renderField}
label={`Hobby #${index + 1}`}
/>
</li>
)}
{error &&
<li className="error">
{error}
</li>}
</ul>
const renderMembers = ({ fields, meta: { error, submitFailed } }) =>
<ul>
<li>
<button type="button" onClick={() => fields.push({})}>
Add Member
</button>
{submitFailed &&
error &&
<span>
{error}
</span>}
</li>
{fields.map((member, index) =>
<li key={index}>
<button
type="button"
title="Remove Member"
onClick={() => fields.remove(index)}
/>
<h4>
Member #{index + 1}
</h4>
<Field
name={`${member}.firstName`}
type="text"
component={renderField}
label="First Name"
/>
<Field
name={`${member}.lastName`}
type="text"
component={renderField}
label="Last Name"
/>
<FieldArray name={`${member}.hobbies`} component={renderHobbies} />
</li>
)}
</ul>
const FieldArraysForm = props => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form onSubmit={handleSubmit}>
<Field
name="clubName"
type="text"
component={renderField}
label="Club Name"
/>
<FieldArray name="members" component={renderMembers} />
<div>
<button type="submit" disabled={submitting}>
Submit
</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>
Clear Values
</button>
</div>
</form>
)
}
export default reduxForm({
form: 'fieldArrays', // a unique identifier for this form
validate
})(FieldArraysForm)
Thanks to the Redux Form team:
https://github.com/erikras/redux-form/issues/3640
Basically, the way it's done is to pass in an array of initial values to the form when you connect and export it, something like this:
export default reduxForm({
form: "foo",
initialValues: {
rockSingers: ['Axl Rose', 'Brian Johnson']
},
onSubmit: values => {
window.alert( "Submited: \n" + JSON.stringify( values, null, 2 ) );
}
})( MyForm );

Categories

Resources