Formik - How to reset form after confirmation - reactjs

In Formik, how to make the Reset button reset the form only after confirmation?
My code below still resets the form even when you click Cancel.
var handleReset = (values, formProps) => {
return window.confirm('Reset?'); // still resets after you Cancel :(
};
return (
<Formik onReset={handleReset}>
{(formProps) => {
return (
<Form>
...
<button type='reset'>Reset</button>
</Form>
)}}
</Formik>
);

Hello #Aximili you can use resetForm in onSubmit.
onSubmit={(values, { resetForm }) => {
// do your stuff
resetForm();
}}
what resetForm can do?
Imperatively reset the form. This will clear errors and touched, set isSubmitting to false, isValidating to false, and rerun mapPropsToValues with the current WrappedComponent's props or what's passed as an argument. The latter is useful for calling resetForm within componentWillReceiveProps.

I'm not completely certain, but I think you will have to write your own reset function without a button with a reset type. Something like this:
const handleReset = (resetForm) => {
if (window.confirm('Reset?')) {
resetForm();
}
};
function Example() {
return (
<Formik initialValues={{ value: 1 }}>
{formProps => {
return (
<Form>
<Field name="value" type="number" />
<button
onClick={handleReset.bind(null, formProps.resetForm)}
type="button"
>
Reset
</button>
</Form>
);
}}
</Formik>
);
}
If you really want to use onReset, I think the only way is to throw an error. The Formik source code seems to indicate resetForm() will be called no matter what your onReset() function returns.
const handleReset = () => {
if (!window.confirm('Reset?')) {
throw new Error('Cancel reset');
}
};
function Example() {
return (
<Formik initialValues={{ value: 1 }} onReset={handleReset}>
{formProps => {
return (
<Form>
<Field name="value" type="number" />
<button type="reset">
Reset
</button>
</Form>
);
}}
</Formik>
);
}
I would still go with the first solution though personally.

I understand OP's question was for Formik.
However, for anyone using useFormik hook and wanting to clear form on 'reset' button click, here's one way to achieve that.
<button type="reset" onClick={ e => formik.resetForm()}> Reset</button>

My issue was I did not wanted to use window.confirm(). I wanted to use my own modal so I used
useFormikContext()
You can create a function component like this
let resetPresForm = {};// You will have to define this before useEffect
const ResettingForm = () => {
const { resetForm } = useFormikContext();
resetPresForm = resetForm; // Store the value of resetForm in this variable
return null;
};
Now Import this function component inside your
<Formik>
<button type="button" onClick={() => { setShowResetModal(true) }} className="comman-btn">Reset</button>
<ResettingForm />
</Formik>
Now on modal component confirm you can
const resetPrescriptionForm = () => {
setShowResetModal(false);
resetPresForm();
}
Reference

in 2023
formik.resetForm(); this worked for me.
here is the complete code for onSubmit event
onSubmit:(values)=>{
const name = values.name;
const mobile = values.mobile;
const website = values.website;
const service = values.service;
const msg = values.msg;
axios.post('/api/SendContactForm', {name, mobile, website, service, msg})
.then(function (response) {
//console.log(response);
toast.success('👋 Thanks for the message. We will contact you asap.');
formik.resetForm();
})
.catch(function (error) {
console.log(error);
formik.resetForm();
toast.error(error.message || error.statusText);
});
}
});

Here is the solution:
<Formik
initialValues={initialValues}
onSubmit={async (values, { resetForm }) => {
await onSubmit(values)
resetForm()
}}>
Reset the form on submit immediately.
I'm not using a custom wrapper around Formik.

I used actions.resetForm() and It resolved the problem.
onSubmit={(values, actions) => {
actions.resetForm();
}}

Related

How to disable a submit button if no changes were made in an input field?

I have an issue where I have multiple input fields with user's data from the database and he can edit them. The form is working fine, although, even when nothing is changed, the submit button is enabled. How do I disable it?
Here is the function part of my code:
const handleUpdateData = async (ProfileData: any) => {
const {
name,
surname,
description,
company,
} = ProfileData;
const dataUsername = {
name,
surname,
company,
description,
}
await mutateAsync({
userId: user?._id,
dataUsername
}).then(res => {
console.log('success')
})
await queryClient.refetchQueries('current-user')
}
and one input controller
<Controller
control={control}
render={({onChange, onBlur, value}) => (
<TextField
name='name'
variant="outlined"
className={classes.input}
onChange={onChange}
onBlur={onBlur}
value={value}
/>
)}
name="name"
rules={{required: true}}
defaultValue={user.name}
/>
and the submit button
<Button onClick={handleSubmit(handleUpdateData)}>
{'save'}
</Button>
Thanks a lot :)
I do not know how your handleSubmit function looks like but this is how i handle it, assuming the *default value are from props. I'm using lodash's isEqual but you can use other object comparison functions.
const Component = (props) => {
const [ state, setState ] = useState(props);
const handleChange = (value) => {
setState({...state, field: value}) //example of state change
}
return (
..... input form
<Button disabled={isEqual(props, state)}></Button>
//using isEqual to compare props and state, if it's different, change happened.
)
}
If you have state in the same component with the input value stored in it just like this
this.state = {
inputValue : ''
};
you can use this prop inputValue to check if it's empty or not like following:
<Button {!this.state.inputValue && "disabled"} onClick={handleSubmit(handleUpdateData)}>
Save
</Button>
Or With Hooks
const [inputValue, setInputValue] = useState("");
<Button {!inputValue && "disabled"} onClick={handleSubmit(handleUpdateData)}>
Save
</Button>

Ant Design Input Component not updating value

I try to get value from backend and append the result to the input field value, but it will not be updated.
Currently I use Ant Design Forms and if input field is moved out of Form it works.
import { version, Input, Form } from "antd";
function View() {
const [LegalName, setLegalName] = useState("");
useEffect(() => {
axios
.get("/afterlogin/OrgFullPictureGet/3", config)
.then(response => {
setLegalName(response.data.name);
})
.catch(error => {
// console.log(error.response.data.errors);
});
}, []);
const onFinish = values => {
//onFinish logic here
console.log(values);
};
return (
<div className="App">
<Form name="nest-messages" onFinish={onFinish}>
<Form.Item
name={["user", "LegalName"]}
label={<span>Legal Name</span>}
>
<Input
placeholder={"Your business legal name"}
value={LegalName}
onChange={e => setLegalName(e.target.value)}
/>
</Form.Item>
</Form>
</div>
);
}
the value does not get appended on the input field
When using name field on the Form.Item, it means that the Form component will handle the value and handleChange on the field from then on. You do not need need to add them. So if you need to add value and handleChange, remove name prop from Form.Item as you see here
But using in most cases, you would want to use them. In that case the alternative is to use the form.setFieldValues to set the required values:
const [form] = Form.useForm();
const [legalName, setLegalName] = useState("");
useEffect(() => {
axios
.get("/afterlogin/OrgFullPictureGet/3", config)
.then(response => {
form.setFieldsValue({
legalName: response.data.name
});
})
.catch(error => {
// console.log(error.response.data.errors);
});
}, []);
return (
<Form name="nest-messages" form={form} onFinish={onFinish}>
<Form.Item name="legalName" label={<span>Legal Name</span>}>
<Input placeholder={"Your business legal name"} />
</Form.Item>
</Form>
);
useForm & setFieldValue Demo docs
Stackblitz Demo

Ant Design Popconfirm confirm on [ENTER]?

How do I make Popconfirm perform the confirm action on [ENTER] key?
render()
{
const { deleteTask, props } = this.props
const onConfirm = (e) =>
{
deleteTask(
{
id: props._id,
})
}
return (
<Popconfirm placement="topRight" title="Delete row?" onConfirm={onConfirm} okText="Yes" cancelText="No">
<Button type="default">
Delete
</Button>
</Popconfirm>
)
}
}
If you what to perform any action using enter key word for that you need to keep the entire input fields within form and submit the form.
handleSubmit = ()=>{
// submit logic here
}
<form onSubmit={(e) => { e.preventDefault(); this.handleSubmit() }} >
// input fields here
<button type="submit" />
</form>
To check if user has clicked Enter key:-
First, <Button onClick={(event) => this.clickHandler(event)} >Click</Button>
clickHandler = (event) => {
if(event.key === 'Enter'){
// do some stuff
}
}
This code works with every library as this is vanilla javascript.

Calling a function for a generate button

I have a page where a user can search a database for a given condition, then the data is returned with another button that the user can use to add information back to the database. However whenever I click on the second button, the page reloads. I can't get so much as a console.log to go in. I'm new to react and could use any help at all.
import React , { Component } from 'react';
import { database } from '../firebase';
const byPropKey = (propertyName, value) => () => ({
[propertyName]: value,
});
class Search extends Component{
constructor(props) {
super(props);
this.state={
users: null,
searchCondition: "",
friend: ""
}
// this.setState = this.setState.bind(this);
}
onSubmit = (event) => {
let {
searchCondition,
friend
} = this.state;
database.searchConditions(searchCondition).then(snapshot =>
this.setState(() => ({ users: snapshot.val() }))
);
event.preventDefault();
}
messageSubmit = (event) => {
console.log("Click")
}
render(){
let {
users,
searchCondition,
friend
} = this.state;
return(
<div>
<h1>Search for conditions</h1>
<form onSubmit={this.onSubmit}>
<div className="search">
<input
value={searchCondition}
onChange={event => this.setState(byPropKey('searchCondition', event.target.value))}
type="text"
placeholder="Condition to Search For"
/>
<button className="friendButton"
onClick="x"
type="submit">
Search
</button>
</div>
</form>
{!!users && <UserList users={users} />}
</div>
)
}
}
let UserList = ({ users, message }) =>
<div>
<h2>List of Usernames and Conditions of your Search</h2>
{Object.keys(users).map(key =>
<div key={key}>{users[key].username} : {users[key].condition}
<form>
<div className="search">
<input
value={message}
onChange={console.log("test")}
type="text"
placeholder="Message for this User"
/>
<button className="messageButton"
onClick={console.log(message)}
type="submit">
Message
</button>
</div>
</form>
</div>
)}
</div>
export default Search;
Have you tried to place the event.preventDefault() at the beginning of the event handler?
It should prevent the default behaviour imediately as the event gets fired.
Hope it works!
a couple things i can see, youre even.preventDefault() should be at the top of the page, you said it was reloading so thats unwanted behavior. second you should set state within the then, generally speaking in my experience that doesnt work- i believe due to setState being asynchronous or something of that nature.
i would rewrite your submit like this
onSubmit = (event) => {
event.preventDefault();
let {
searchCondition,
friend
} = this.state;
let value;
database.searchConditions(searchCondition).then(snapshot =>
value = snapshot.val
);
this.setState(() => ({ users: value) }))
}
also likely the reason your "messageSubmit()" was not console logging is because youre using a submit handler not a click handler so everytime your clicked you were reloading the page.
cheers

How to submit a form using Enter key in react.js?

Here is my form and the onClick method. I would like to execute this method when the Enter button of keyboard is pressed. How ?
N.B: No jquery is appreciated.
comment: function (e) {
e.preventDefault();
this.props.comment({
comment: this.refs.text.getDOMNode().value,
userPostId:this.refs.userPostId.getDOMNode().value,
})
},
<form className="commentForm">
<textarea rows="2" cols="110" placeholder="****Comment Here****" ref="text" /><br />
<input type="text" placeholder="userPostId" ref="userPostId" /> <br />
<button type="button" className="btn btn-success" onClick={this.comment}>Comment</button>
</form>
Change <button type="button" to <button type="submit". Remove the onClick. Instead do <form className="commentForm" onSubmit={onFormSubmit}>. This should catch clicking the button and pressing the return key.
const onFormSubmit = e => {
e.preventDefault();
// send state to server with e.g. `window.fetch`
}
...
<form onSubmit={onFormSubmit}>
...
<button type="submit">Submit</button>
</form>
It's been quite a few years since this question was last answered.
React introduced "Hooks" back in 2017, and "keyCode" has been deprecated.
Now we can write this:
useEffect(() => {
const listener = event => {
if (event.code === "Enter" || event.code === "NumpadEnter") {
console.log("Enter key was pressed. Run your function.");
event.preventDefault();
// callMyFunction();
}
};
document.addEventListener("keydown", listener);
return () => {
document.removeEventListener("keydown", listener);
};
}, []);
This registers a listener on the keydown event, when the component is loaded for the first time. It removes the event listener when the component is destroyed.
Use keydown event to do it:
input: HTMLDivElement | null = null;
onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): void => {
// 'keypress' event misbehaves on mobile so we track 'Enter' key via 'keydown' event
if (event.key === 'Enter') {
event.preventDefault();
event.stopPropagation();
this.onSubmit();
}
}
onSubmit = (): void => {
if (input.textContent) {
this.props.onSubmit(input.textContent);
input.focus();
input.textContent = '';
}
}
render() {
return (
<form className="commentForm">
<input
className="comment-input"
aria-multiline="true"
role="textbox"
contentEditable={true}
onKeyDown={this.onKeyDown}
ref={node => this.input = node}
/>
<button type="button" className="btn btn-success" onClick={this.onSubmit}>Comment</button>
</form>
);
}
this is how you do it if you want to listen for the "Enter" key.
There is an onKeydown prop that you can use and you can read about it in react doc
and here is a codeSandbox
const App = () => {
const something=(event)=> {
if (event.keyCode === 13) {
console.log('enter')
}
}
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<input type='text' onKeyDown={(e) => something(e) }/>
</div>
);
}
import React, { useEffect, useRef } from 'react';
function Example() {
let inp = useRef();
useEffect(() => {
if (!inp && !inp.current) return;
inp.current.focus();
return () => inp = null;
});
const handleSubmit = () => {
//...
}
return (
<form
onSubmit={e => {
e.preventDefault();
handleSubmit(e);
}}
>
<input
name="fakename"
defaultValue="...."
ref={inp}
type="radio"
style={{
position: "absolute",
opacity: 0
}}
/>
<button type="submit">
submit
</button>
</form>
)
}
Enter code here sometimes in popups it would not work to binding just a form and passing the onSubmit to the form because form may not have any input.
In this case if you bind the event to the document by doing document.addEventListener it will cause problem in another parts of the application.
For solving this issue we should wrap a form and should put a input with what is hidden by css, then you focus on that input by ref it will be work correctly.
If you don't have the form inside <form>, you could use this in componentDidMount():
componentDidMount = () => {
document.addEventListener("keydown", (e) =>
e.code === "Enter" && console.log("my function"))
}
componentDidMount() //<-- remove this, it's just for testing here
useEffect(() => {
const keyEnter = event => {
if (event.key === 'Enter') {
event.preventDefault()
}
}
document.addEventListener('keydown', keyEnter)
return () => {
document.removeEventListener('keydown', keyEnter)
}
}, [])
I've built up on #user1032613's answer and on this answer and created a "on press enter click element with querystring" hook. enjoy!
const { useEffect } = require("react");
const useEnterKeyListener = ({ querySelectorToExecuteClick }) => {
useEffect(() => {
//https://stackoverflow.com/a/59147255/828184
const listener = (event) => {
if (event.code === "Enter" || event.code === "NumpadEnter") {
handlePressEnter();
}
};
document.addEventListener("keydown", listener);
return () => {
document.removeEventListener("keydown", listener);
};
}, []);
const handlePressEnter = () => {
//https://stackoverflow.com/a/54316368/828184
const mouseClickEvents = ["mousedown", "click", "mouseup"];
function simulateMouseClick(element) {
mouseClickEvents.forEach((mouseEventType) =>
element.dispatchEvent(
new MouseEvent(mouseEventType, {
view: window,
bubbles: true,
cancelable: true,
buttons: 1,
})
)
);
}
var element = document.querySelector(querySelectorToExecuteClick);
simulateMouseClick(element);
};
};
export default useEnterKeyListener;
This is how you use it:
useEnterKeyListener({
querySelectorToExecuteClick: "#submitButton",
});
https://codesandbox.io/s/useenterkeylistener-fxyvl?file=/src/App.js:399-407
I have found this to be easier.
Listen for the keyDown event on the input you want to submit by pressing 'Enter" key and handle the submit action with conditional ternary operator as show below in a single line.
This is mostly used on subscribing a newsletter where there's no need of a button to submit.
Hope it helps.
<input
type="email"
placeholder="Email"
onKeyDown={e => e.key === 'Enter' ? handleSubmit : ''} />
You can use <button type='submit'></button> with nothing in the middle.
here is very optimised code
useEffect(() => {
document
.getElementById("Your-element-id")
.addEventListener("keydown", function (event) {
if (event.code === "Enter" || event.code === "NumpadEnter") {
event.preventDefault();
document.getElementById("submit-element").click();
}
});
}, []);
use mousetrap
https://www.npmjs.com/package/mousetrap
https://www.npmjs.com/package/#types/mousetrap
(yeah, I know, unfortunatelly when You use typescript u have to install types aside from basic module)
import {bind} from 'mousetrap';
const handleSubmit = async () => {
// submit func here
};
bind(['enter', 'return'], handleSubmit);
other example of using mousetrap, maybe for other purpose:
bind(['command+k', 'ctrl+k'], function(e) {
highlight([11, 12, 13, 14]);
return false;
});
So, I was looking for some solution around the same scenario where on the login page, after a user hits(press) enter button from keyboard should trigger login process.
You can configure the textbox with one of code,
<input
// rest your code
onKeyPress={ onkeyup }
/>
Please keep in mind I am using react hooks to achieve it, apart from that this link will help you understand more enter key event handler
Try this enter code here:
const enterKye=()=>{
if(e.key==="Enter"){
alert("hello");
}
}
<input type="text" onKeyPress={enterKye}>
You may approach this problem like this.
onKeyPress={e => e.key === 'Enter' && handleFormSubmit}
You can change only button type => button to submit
<form
onSubmit={e => {
e.preventDefault();
handleSubmit(e);
}}
>
<input
name="developers"
defaultValue="submit"
ref={dev}
type="radio"
/>
<button type="submit">
submit
</button>
</form>
for example next React+TS code(add use hooks for state and etc):
type Props = {
...any properties
} & [any other type if need]
//I want notice that input data type of component maybe difference from type of props
const ExampleComponent: React.FC<Props> = (props: [Props or any other type]){
const anySerice = new AnyService();
const handleSubmit = async (eventForm) => {
await anySerice.signUp();
}
const onKeyUp = (event: KeyboardEvent) => {
//you can stay first condition only
if (event.key === 'Enter' || event.charCode === 13) {
handleSubmit(event)
}
}
...other code
return (<Form noValidate validated={validated} className="modal-form-uthorize" onKeyPress={onKeyUp}>
...other components form
</Form>)
}
export default ExampleComponent;
I solved this problem by sent autoFocus property in button
<button autoFocus={true}></button>

Resources