Get the value from input of Formik's Field - javascript

There is a Formik field for validating some data, it looks like this:
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={values => this.handleDelete(values)}>
{({ values, errors, touched, setFieldValue }) => (
<Form>
<Field
className="add-input"
name="deleteText"
as={Input}
placeholder="Write DELETE"
/>
</Form>
)}
</Formik>
If I write a text, "abc" in the input, with DevTools in Inspect mode this looks like this:
<form action ="#">
<div class="ui input add-input">
<input name="deleteText" placeholder="Write DELETE" type="text" value="abc">
</div>
</form>
Here it can be seen the introduced text, but how can I access it that text from the code?

You can use values[<name>] like values['deleteText'] for your code (inside the render function of the Formik)
or
You can pass onChange prop to the <Field>

Related

form.validateFields() doesnt work when we have custom antd form component

Considering the following example, this is stopping us to create custom components inside forms using antd4 version.
const handleFormSubmit = () => {
form
.validateFields()
.then((values: any) => {
console.log('success values => ', JSON.stringify(values));
successCallback(values);
})
.catch((errorInfo: any) => {
console.log('failureCallback values => ', JSON.stringify(errorInfo));
failureCallback(errorInfo);
});
};
<Form
form={form}
layout="vertical"
name="normal_login"
className="login-form"
initialValues={store.formData.initialValues}
>
<Form.Item>
<Input placeholder="Name" />
</Form.Item>
<Button type="primary" htmlType="submit" onClick={handleFormSubmit}>
Create
</Button>
</Form>
This works absolutely fine, whereas if the component is custom, then it doesn't work. Example:
function CustomInput(props){
return (
<Form.Item>
<Input placeholder={props.name} />
</Form.Item>
)
}
<Form
form={form}
layout="vertical"
name="normal_login"
className="login-form"
initialValues={store.formData.initialValues}
>
<CustomInput name="Name" />
Will display the field and also validates on change event. HandleFormSubmit is called, but it's not triggering success or failure block.
<Button type="primary" htmlType="submit" onClick={handleFormSubmit}>
Create
</Button>
</Form>
What's wrong here?
Try this instead of your Custom JSX
function CustomInput(props){
return (
<Form.Item name={props.name}> # Update this line only and remove this comment #
<Input placeholder={props.name} />
</Form.Item>
)
}
<Form
form={form}
layout="vertical"
name="normal_login"
className="login-form"
initialValues={store.formData.initialValues}
>
<CustomInput name="Name" />
<Button type="primary" htmlType="submit" onClick={handleFormSubmit}>
Create
</Button>
</Form>
NOTE: In Antd if your using Form.Item then you have to set name there
not on input fields. Form.Item assign its value to its Input.
I hope your doubt is solved comment for more views. I also tired of antd and wasted many days to understand this.

Validating Final Form Array on Click

I am building an application with React Final Form. In the form, user needs to fill up basic input fields as well as add questions with its choices. For the questions and choices I am using FieldArray feature. So, until here everything is good and working. However, I would like to add another functionality to this form.
As you can see in the image below, this is a Card component rendered inside FieldArray. Every time user clicks Add a Question button, There will be another Card component on the page.
The feature I need is to make the Save button work on top-right corner. At the moment I don't know how should I implement the Save button but what I wanna achieve is that I want to toggle the Card component in the image to another Card component, where I display the input data by using fields.value. So, no input field. However, I want to also validate this portion of the form when I click save. This is what I don't know how to do. So, every Save button will validate its own fields and if validation passes, the Card will be toggled to another Card component where the data is read-only.
So, I need your suggestion for the validation part as well as your opinion to add this functionality.
Thanks
Edit
I've been reading the docs of FinalForm as well as ReduxForm to figure out how can I handle this situation but I couldn't figure it out yet.
I've checked the Wizard example in FinalForm docs. However I am not sure if it's suitable for my situation. Wizard has a single <form> tag present at all times on a page and when a user clicks next button, input fields switch. In my case, I might need multiple form tags as you mentioned.
I've put 3 form structures as an example. Can you tell me which way is to go?
import { Form as FinalForm } from 'react-final-form'
#1 Basic Form:
Classic way of structuring the form and it is the current situation. So, this is not the way to solve the issue.
<FinalForm onSubmit={aCustomSubmitFunction}>
{
({ handleSubmit }) => {
return (
<form onSubmit={handleSubmit}>
<Field name='firstName'>{({input}) => <input {...input} />}</Field>
<Field name='lastName'>{({input}) => <input {...input} />}</Field>
<FieldArray name='questions'>
{({ fields }) => (
<div>
{fields.map((name, index) => {
return (
<div className="card">
<Field name={`${name}.question`}>{({input}) => <input {...input} type="text" />}</Field>
<button type="button" onClick={() => fields.remove(index)}>Delete</button>
<button type="submit">Save</button>
</div>
)
})}
<button type="button" onClick={() => fields.push({ question: undefined })}>Add a Question</button>
</div>
)}
</FieldArray>
<button type="submit">Submit</button>
</form>
)
}
}
</FinalForm>
#2 Multiple forms under a single FinalForm:
Multiple forms inside a FinalForm. This seems to be the way to go, however 'save' button submits the entire form not its own form. It is using the same handleSubmit so this must be the reason, though how can I have a different handleSubmit? Wrapping the form tag that is inside FieldArray with another FinalForm?
<FinalForm onSubmit={aCustomSubmitFunction}>
{
({ handleSubmit }) => {
return (
<>
<form onSubmit={handleSubmit}>
<Field name='firstName'>{({input}) => <input {...input} />}</Field>
<Field name='lastName'>{({input}) => <input {...input} />}</Field>
<button type="submit">Submit</button>
</form>
<FieldArray name='questions'>
{({ fields }) => (
<div>
{fields.map((name, index) => {
return (
<form onSubmit={handleSubmit}>
<div className="card">
<Field name={`${name}.question`}>{({input}) => <input {...input} type="text" />}</Field>
<button type="button" onClick={() => fields.remove(index)}>Delete</button>
<button type="submit">Save</button>
</div>
</form>
)
})}
<button type="button" onClick={() => fields.push({ question: undefined })}>Add a Question</button>
</div>
)}
</FieldArray>
</>
)
}
}
</FinalForm>
#3 Multiple nested forms under a single FinalForm:
This is invalid html. So this must be wrong approach but while I was doing a research I found a thing called React Portals, which might be helpful but I think it's unnecessary.
<FinalForm onSubmit={aCustomSubmitFunction}>
{
({ handleSubmit }) => {
return (
<form onSubmit={handleSubmit}>
<Field name='firstName'>{({input}) => <input {...input} />}</Field>
<Field name='lastName'>{({input}) => <input {...input} />}</Field>
<FieldArray name='questions'>
{({ fields }) => (
<div>
{fields.map((name, index) => {
return (
<form>
<div className="card">
<Field name={`${name}.question`}>{({input}) => <input {...input} type="text" />}</Field>
<button type="button" onClick={() => fields.remove(index)}>Delete</button>
<button type="submit">Save</button>
</div>
</form>
)
})}
<button type="button" onClick={() => fields.push({ question: undefined })}>Add a Question</button>
</div>
)}
</FieldArray>
<button type="submit">Submit</button>
</form>
)
}
}
</FinalForm>
To validate only part of a form, you must split it into multiple forms, and have the "Save" button "submit" the form. The Wizard Example does this, collecting the form values from each "page" in a parent component.
Hope this helps...

React Formik: How to set default value in formik when click the checkbox?

I have a form that uses the formik react library. When clicking the checkbox I want to fill some data inside an input field in that. I don't know how to do that in a Formik way.
Anyone please help me to solve this issue?
Code I tried :
<Formik initialValues={{ email: ''}}>
{({errors, touched, setFieldValue, handleSubmit, handleBlur, handleChange, isSubmitting}) => {
return (<Form onSubmit={handleSubmit}>
{console.log('touched',touched, errors)}
<div className="upload-container">
OFFICIAL EMAIL
<input onBlur={handleBlur} onChange={handleChange} id="email_id" name="email" type="email"/>
<div className="email-error__message__div">
{errors.email && touched.email ? errors.email : ''}
</div>
<div className="official-MailID__container">
<input
id="checkOffiMailId"
name="checkofficialmailId"
type="checkbox" />
</div>
</div>
<div className="button__container">
<button className="verify-me" type="submit" disabled={isSubmitting}>VERIFY ME</button>
<button className="doit-later" onClick={doItLater}>I'LL DO THIS LATER</button>
</div>
</Form>
)}}
</Formik>
I updated the question. What I want is when I clicked the checkOffiMailId I want to fill some data in email_id.
Formik Library

React Formik Field onChange event handle

I am trying to handle onChange for Field component in React Formik, but it doesn't work. I also tried to handle it outside Formik component by:
handleChange(e) {
console.log('changing');
}
<Field type="radio" name="players" value="1" onChange={e => this.handleChange(e)}/>
but I am getting the warning:
A component is changing an uncontrolled input of type text to be
controlled. Input elements should not switch from uncontrolled to
controlled (or vice versa).
For now my code looks like this:
<Formik
onChange={() => {
console.log('changing');
}}
onSubmit={(values) => {
console.log('submitted');
}}
>
{({ isSubmitting, handleChange }) => (
<Form>
<InputWrapper>
<span>1</span>
<Field type="radio" name="players" value="1" onChange={handleChange}/>
<span>2</span>
<Field type="radio" name="players" value="2" onChange={handleChange}/>
</InputWrapper>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? 'Loading..' : 'Start'}
</button>
</Form>
)}
</Formik>
Any tips/ideas?
One issue I have found with introducing the onBlur:handleBlur to your Formik Field is that it overrides the Formik Validation.
Use onKeyUp={handleChange}
This solved said problem
You must to use the InputProps of Field like the following...
import { TextField } from 'formik-material-ui';
<Field
type="radio"
name="players"
value="2"
component={TextField}
InputProps={{ onBlur:handleBlur }}/>
To use the InputProps in the Field you need to use a component TextField from the formik-material-ui lib.
Another way is use the onKeyUp or onKeyDown, that functions work ok with Field and that functions are like onChange
<Field
type="radio"
name="players"
value="2"
onKeyUp =this.handleChange/>
I found one trick which worked well for me, you can use "values" of formik and call a method passing the "values" as parameter and perform the action using new values.
const handleUserChange = (userId: number) => {
//userId is the new selected userId
};
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleSubmit}
enableReinitialize
>
{({ isValid, isSubmitting, values }) => (
<Form>
<table className="table">
<tbody>
<tr>
<td>Users</td>
<td>
<Field name="userId" className="form-control" as="select">
<option value="">--select--</option>
{data.Users.map((user, index) => (
<option key={user.id} value={user.id}>{`User ${index + 1}`}</option>
))}
</Field>
</td>
</tr>
{handleUserChange(values.userId)}
</tbody>
</table>
<div className="row">
<div className="col-sm-12">
<SubmitButton label="Save" submitting={isSubmitting} disabled={!isValid || isSubmitting} />
</div>
</div>
</Form>
)}
</Formik>

Display emoji object to text field or textarea in React

I'm building my app with emoji-mart lib.
I have text input like this:
<FormGroup>
{emoji}
<EmojiMartPicker
set='emojione'
onSelect={(emoji) => console.log(emoji)}
onChange={this.onChange}
>
<Input
type="text"
name="emotion"
bsSize="sm"
autoComplete="off"
value={report.emotion.colons}
onChange={this.onHandleFormChange}
required
/>
</EmojiMartPicker>
</FormGroup>
Now, I wanna display Emoji Object to text input. In value attribute. I want to display emoji, not value text.
How can we do that?
See my detail problem:
https://codesandbox.io/s/646xom9y1z
Sorry, I found that just only add native props to solved my problem.
Like this:
value={report.emotion.native}
That's it..
I solve this problem take a look.
<div className="chatemoji">
<ButtonToolbar >
<div onClick={e => e.preventDefault()}>
{/* <EmojiField
name="textarea"
onChange={this.onChange.bind(this)}
fieldType="input"
/> */}
<EmojiField name="my-textarea" onChange={this.onChange.bind(this)} fieldType="input" />
</div>
</ButtonToolbar>
</div>
In onChange you have to call this code
onChange(e,value) {
this.state.data += value;
this.setState({ data: this.state.data });
}

Categories

Resources