Using formik how to add values to formik values when TypeAhead field is selected - formik

I'm using formik for my form with a TypeAhead field that allow the user to select array of objects. I want to update Formik values with the array of objects when selected. How do I update formik values when the value has been selected? I have tried setFieldValue, but how can it be done in this manner?
<Formik
initialValues={{
driverList: [
{
id:'',
firstName: '',
lastName: '',
smsPhone: '',
email: ''
}
],
}}
validationSchema={Yup.object({
activateAccount: Yup.boolean()
.required('Required')
.oneOf([true], 'Account must be activated.'),
})}
onSubmit={values => {
alert(JSON.stringify(values, null, 4));
console.log(values)
}}
>
{({handleSubmit, setFieldValue, values}) => (
<div>
<Card className="callSupportCard">
<Card.Body>
<Card.Title className="callSupportTitle">
Account Activation
</Card.Title>
<Card.Subtitle className="callSupportCheckBox">
The customer has started to setup up his/her account but could not finish.
</Card.Subtitle >
<p className="callQuestion">{" "}<b>Step 1:{" "}</b> Ask for their first and last name.</p>
<Form onSubmit={handleSubmit}>
<Typeahead className="driverInput" id="driversInfo"
labelKey={(option) => `${option.firstName} ${option.lastName}, ${option.smsPhone}, ${option.email}`}
onChange={setSelected}
options={options}
selected={selected}
placeholder="Choose an driver..."
/>

Solution was:
<Typeahead
labelKey={(option) => `${option.firstName} ${option.lastName}, ${option.phone}, ${option.email}`}
onChange={(selected) => {
if(selected.length > 0)
{setFieldValue('firstName', selected[0].firstName);
setFieldValue('lastName', selected[0].lastName);
setFieldValue('smsPhone', selected[0].phone);
setFieldValue('email', selected[0].email);
setFieldValue('suspended', selected[0].suspended);
}}}
options={options}
placeholder="Choose an person..."
/>

Related

React Formik props isSubmitted with react-query do not take affect

I have my Formik form below (I'm new with formik). An this is the simple form which have two fields and makes api call using react-query (react -query works well).
But the problem is that formik state isSubmitting do not take effect when click. (Button do not start spinning, but if it is direct true, it works well)
I wonder what i'm missing? Why it has no effect? and How it could be solved?
Api Call:
const createUser = async ({name, password}: Record<string, string>) => {
return await axiosInstance.post(`users/create_user/`, {
name: name,
password: password,
});
};
React-query Mutation:
const createNewUser = useMutation(createUser, {
onSuccess: () => {
queryClient.refetchQueries(["getAllUsers"])
},
onError: (newUser) => {
console.log("onError", newUser);
}
Formik Form:
<Formik
initialValues={{ username: username, password: password }}
validateOnChange={false}
validateOnBlur={false}
onSubmit={(values, {setSubmitting, resetForm }) => {
setSubmitting(true)
createNewUser.mutate({
name: values.username,
password: values.password,
});
setSubmitting(false);
resetForm();
}}
>
{({ values, errors, isSubmitting, handleSubmit }) => (
<form onSubmit={handleSubmit}>
<div>
<label
htmlFor="Имя"
className="block text-900 font-medium mb-2"
>
</label>
<Field
type="text"
name="username"
className="w-full mb-3"
as={InputText}
/>
<Field
type="text"
name="password"
className="w-full mb-3"
as={InputText}
/>
<Button
label="save new user"
icon="pi pi-user"
className="w-full"
type="submit"
loading={isSubmitting} // to not take effect? why?
/>
</div>
</form>
Try using setTimeout, to setSubmitting(false) after few seconds not immediately like this:
setTimeout(() => setSubmitting(false), 2000);
Or, check if mutation is successfully executed, then setSubmitting to false
if(createNewUser.status == 'success' || createNewUser.status == 'error') {
setSubmitting(false);
}
Alternatively, without using formik isSubmitting you can use
createNewUser.isLoading
<Button
label="save new user"
icon="pi pi-user"
className="w-full"
type="submit"
loading={createNewUser.isLoading}
/>

Can't get Formik form to work with Material UI

I'm struggeling with making my Formik form work. Here a part of my code:
import { Formik, Form as FormikForm, Field } from "formik";
import {TextField} from "#mui/material";
<Formik
initialValues={{
name: "test",
}}
onSubmit={this.onSubmit}
>
{({ values,handleChange }) => (
<FormikForm>
<Field
component={TextField}
name="name"
label="Name"
fullWidth
></Field>
<Button
color="success"
variant="contained"
type="submit"
onClick={() => {
console.log(values);
}}
>
Erstellen
</Button>
</FormikForm>
)}
</Formik>
It seems like its having trouble connecting the values state to the Field value, since the initialValue isn't displayed in the names field. When i submit, it logs {name: 'test'} to console, no matter what i enter in the input field.
Edit 1:
I also have a very similar form that works. The only difference between the two that i can think of is: the working one is a .jsx while this one is .tsx. Dont know if that has anything to do with it.
According to the Field documentation you need to spread the field and pass it to the component like this:
import { Formik, Form as FormikForm, Field } from "formik";
import { Button, TextField } from "#mui/material";
const MuiTextField = ({ field, form, ...props }) => {
return <TextField {...field} {...props} />;
};
const MyComponent = () => {
return (
<Formik
initialValues={{
name: "test"
}}
onSubmit={(values) => {
console.log(values);
}}
>
{({ values, handleChange }) => (
<FormikForm>
<Field
component={MuiTextField}
name="name"
label="Name"
fullWidth
></Field>
<Button
color="success"
variant="contained"
type="submit"
onClick={() => {
console.log(values);
}}
>
Erstellen
</Button>
</FormikForm>
)}
</Formik>
);
};
export default MyComponent;
You can take a look at this sandbox for a live working example of this solution.
Like Ahmet pointed out, the problem seems to be that the field prop needs to be spread (see his answer). However i found, that using as instead of component works too and doesnt need spreading.
<Field
as={TextField}
name="name"
label="Name"
fullWidth
></Field>

Formik does not update value from input

I am trying to add Form to my application, so I decided to pick formik and I ran into a little problem
I have following components:
After typing something in input, I am clicking submit and alert appears with empty data like:
{
someName: ''
}
Why someName does not update?
const SearchInput = ({name, ...props}) => {
const [field] = useField(name);
return (
<Styled.Wrapper>
<Styled.Input {...field} {...props} placeholder="Search" />
</Styled.Wrapper>
);
};
const Form = () => {
return (
<Formik
initialValues={{
someName: '',
}}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
>
{(props: FormikProps<Values>) => (
<FormikForm>
<SearchInput
name="someName"
type="text"
label="Some Name"
onChange={props.handleChange}
value={props.values.jobName}
/>
<button type="submit">Submit</button>
</FormikForm>
)}
</Formik>
)
};
export default Form;

Formik - TextField does not accept numeric value when using react-number-format

I'm using react-number-format library if numeric values is set to TextField it will not show any error after reset the form.
t should accept the numeric values also like other string values.
Here is my code you are reproduce error from this.
Formik Form
<Formik
enableReinitialize
initialValues={{
area: "",
password: "",
}}
validate={(values) => {
const errors: Partial<Values> = {};
if (!values.area) {
errors.area = "Required area";
}
return errors;
}}
onSubmit={(values, { setSubmitting, resetForm }) => {
setTimeout(() => {
setSubmitting(false);
console.log(JSON.stringify(values, null, 2));
resetForm();
}, 500);
}}
>
{({ submitForm, isSubmitting }) => (
<Form>
<Field
component={TextField}
name="area"
label="area"
InputProps={{
inputComponent: NumberField,
}}
/>
<br />
<Field
component={TextField}
type="password"
label="Password"
name="password"
/>
{isSubmitting && <LinearProgress />}
<br />
<Button
variant="contained"
color="primary"
disabled={isSubmitting}
onClick={submitForm}
>
Submit
</Button>
</Form>
)}
</Formik>
NumberField
import NumberFormat from "react-number-format";
interface NumberFieldProps {
name: string;
inputRef: (instance: NumberFormat<any> | null) => void;
onChange: (event: {
target: { name: string; value: number | undefined };
}) => void;
}
export default function NumberField(props: NumberFieldProps) {
const { inputRef, onChange, ...other } = props;
return (
<NumberFormat
{...other}
getInputRef={inputRef}
onValueChange={(values) => {
onChange({
target: {
name: other.name,
value: values.floatValue,
},
});
}}
/>
);
}
Click on submit button and you will see Required area error, Set value in area field and submit form, it submit the form and reset it after that click again on submit button you will see it will not give you Required area error. I don't know why this happen.
Now change value: values.floatValue to value: values.value in NumberField file and everything work well. I don't know why it is not working when I set floatValue I need numeric values not string.

How can I check react-datepicker value with react-hook-form?

I have a register form and use react-hook-form for validation. I want to give an error message if under 15 years old. Is this possible?
here is the picker code
<DatePicker ref={ref} name="birthday" dateFormat="dd/MM/yyyy" disabled={disabled}
selected={startDate || value}
onChange={date => onChangePicker(date)}
maxDate={addDays(new Date()), 1)}
onFocus={() => { focusInput() }}
onBlur={(e) => { blurInput(e) }}
autoComplete="off"
customInput={
<MaskedInput
mask={[/\d/, /\d/, '/', /\d/, /\d/, '/', /\d/, /\d/, /\d/, /\d/]}
/>
}
/>
and here in form
{errors.birthday && <span className="input__error-message birthday-error">Birthday is required</span>}
<Controller
name="birthday"
control={control}
defaultValue={false}
render={({ onChange, value }) => <Calendar label="Birthday" onChange={onChange} value={value} />}
rules={{ required: true }}
register={register}
/>
Yes, this is possible. You just have to use the validate function provided by the rules prop object.
const isOlderThan15Years = date => {...}
rules={{ required: true, validate: date => isOlderThan15Years(date) }}
Check the register section in the documentation for more information.

Resources