React Formik and Checkbox - javascript

I need to map dynamicaly on a array. This array can change with a search field and i need to know what checkbox are checked to send my data with a submit but i dont find the right way to do to check the checkbox with Formik. This is my code :
const initialValues = {
checked: [],
};
const onSubmit = (values) => {
console.log(values);
};
<Formik onSubmit={onSubmit} initialValues={initialValues}>
{({ values, handleSubmit }) => (
<form
onSubmit={handleSubmit}
noValidate={true}
>
{Listing.map((Search, index) => {
if (
Search.installationAddress.includes(
searchMeter
) ||
Search.deviceId.includes(searchMeter)
) {
return (
<div
key={index}
>
<Checkbox
color="text.standard"
label={`${Search.installationAddress}`+" Compteur N° " +`${Search.deviceId}`}
type="checkbox"
name="checked"
value={{
contractAccountId:
Search.contractAccountId,
deviceId: Search.deviceId,
}}
size="large"
/>
</div>
);
}
})}
<Checkbox
color="text.standard"
label="I confirm"
onChange={() => setValidationButton(!validationButton)}
value=""
checked={validationButton}
/>
<Button
type="submit"
disabled={!validationButton}
>
ACTIVATE
</Button>
</form>
)}
</Formik>

Related

React Final Form FieldArray validation on form.restart

I have a form with a fields array. At the bottom of the form there is a button that deletes all list items (in fact, it does form.restart).
When deleting fields, the validation of each field is triggered, but the value of the field is undefined. This breaks the validation logic.
In theory, this validation should not exist at all.
How to get rid of this validation on form.restart?
Code:
(https://codesandbox.io/s/festive-water-6u3t69?file=/src/App.js:0-1477)
import React from "react";
import { Form, Field } from "react-final-form";
import { FieldArray } from "react-final-form-arrays";
import arrayMutators from "final-form-arrays";
import "./styles.css";
export default function App() {
const [values] = React.useState({ items: [] });
const renderForm = ({ form }) => {
return (
<div>
<FieldArray name={"items"}>
{({ fields }) => (
<div>
{fields.map((name, index) => (
<div key={name}>
<Field
name={`${name}.title`}
validate={(value) => console.log(value)}
key={name}
>
{({ input }) => (
<input
value={input.value}
onChange={(event) => input.onChange(event.target.value)}
/>
)}
</Field>
</div>
))}
<button onClick={() => fields.push({ title: "111" })}>
add item
</button>
<button onClick={() => form.restart({ items: [] })}>reset</button>
</div>
)}
</FieldArray>
</div>
);
};
return (
<div className="App">
<Form
onSubmit={() => {}}
initialValues={values}
render={renderForm}
mutators={{ ...arrayMutators }}
/>
</div>
);
}
Thank you.

Formik is Not Rendering Initial Values

I am using Formik for form submission in my React Project.
const initialValues =
submittedAssignment !== undefined
? {
comments: submittedAssignment?.comments,
mk1: mKeys[0],
mk2: mKeys[1],
mk3: mKeys[2],
mk4: mKeys[3],
mk1Num: submittedAssignment?.mk1Num,
mk2Num: submittedAssignment?.mk2Num,
mk3Num: submittedAssignment?.mk3Num,
mk4Num: submittedAssignment?.mk4Num,
}
: {
comments: "",
mk1: "",
mk2: "",
mk3: "",
mk4: "",
mk1Num: 0,
mk2Num: 0,
mk3Num: 0,
mk4Num: 0,
};
console.log(initialValues);
return(
<Formik
initialValues={initialValues}
validationSchema={Yup.object({
comments: Yup.string().required(),
mk1Num: Yup.number().positive().required().max(5),
mk2Num: Yup.number().positive().required().max(5),
mk3Num: Yup.number().positive().required().max(5),
mk4Num: Yup.number().positive().required().max(5),
})}
onSubmit={async (values, { setErrors, setSubmitting }) => {
try {
values = testFunction(values);
console.log(values);
const totalGrade =
values.mk1Num + values.mk2Num + values.mk3Num + values.mk4Num;
const response = await updateSubmittedAssignment(
courseId,
assignmentId,
values,
totalGrade,
studentId
);
if (response.data.data === false)
setErrors({ err: "Error Submitting. Please contact tech" });
else {
setSubmitting(false);
history.push(
`/submittedAssignments/${courseId}/${assignmentId}`
);
}
} catch (error) {
setErrors({ err: error.message });
}
}}
>
{({ isSubmitting, submitForm, isValid, errors }) => (
<Form className="ui form">
<TextArea
name="comments"
placeholder="Enter Comments Here"
rows={10}
/>
<Select
name="mk"
placeholder="Select Marking Key"
options={markingKeys}
onChange={handleMk}
/>
<br />
{mKeys.length > 0 && (
<Grid>
<Grid.Column width={14}>
<TextInput name="mk1" id={1} value={mKeys[0]} />
<TextInput name="mk2" id={2} value={mKeys[1]} />
<TextInput name="mk3" id={3} value={mKeys[2]} />
<TextInput name="mk4" id={4} value={mKeys[3]} />
</Grid.Column>
<Grid.Column width={2}>
<TextInput name="mk1Num" type="number" />
<TextInput name="mk2Num" type="number" />
<TextInput name="mk3Num" type="number" />
<TextInput name="mk4Num" type="number" />
</Grid.Column>
</Grid>
)}
{errors.err && (
<Label
basic
color="red"
style={{ marginBottom: 10 }}
content={errors.err}
/>
)}
<br />
<Button
loading={isSubmitting}
disabled={!isValid || isSubmitting}
type="submit"
fluidsize="large"
color="teal"
content="Submit"
onClick={submitForm}
/>
</Form>
)}
</Formik>
)
Till yesterday, setting the name property in the TextArea and TextInput, the same as the field in the initialValues object was enough to display the initital values. But i dont know what happened, the initial values are not showing up, although when i log them, they have correct values.
Any help is appreciated. Thanks
Try adding enableReinitialize to Formik.
<Formik
enableReinitialize
...
You may have a case where the initialValues values get updated only after the first render.
On the first render Formik takes the initialValues as they are, so if the values didn't get updated yet you will not see them in the form fields.
SOURCE:
https://formik.org/docs/api/formik#enablereinitialize-boolean

Focus next input field after maxLength is full. React.js

Hi I am having a problem with my for and inputs. I have 6 inputs with maxLength = 1 and i want to focus next input when when value is entred.
<Form
form={form}
className={styles.form}
onFinish={onFinish}
initialValues={initialValues}
>
<div className={styles.labeContainer}>
<LabelField name="code">
{({ value, onChange }) => {
return (
<div>
{inputsArr.map((_, index) => (
<Input
key={index}
maxLength={1}
defaultValue={value[index]}
className={styles.codeInput}
onChange={(val) => {
onChange(
value.substring(0, index) +
val.target.value +
value.substring(index + 1)
);
}}
/>
))}
</div>
);
}}
</LabelField>
</div>
</Form>
I was trying to use something with refs but i had no idea how to get this working. Also did some reseasrch on this, but nothing helped. I am using rc-field-form but docs are very vage

get field value from Formik & Material UI form

I am trying to disable a checkbox group based on the value of a radio group. I followed the method used in the last part of the Formik tutorial. Using react context removes a lot of clutter from the form itself but I'm not sure how to expose some values now.
In the form below, in the CheckboxGroup component, I'm attempting to print the word disabled as an attribute of checkbox1 if radio4's value is "yes". I'm not sure what value should be used here as fields doesn't work. How do I pass a value to the form given the React Context method used?
The form:
export default function HealthAssessmentForm() {
return (
<Formik
initialValues={{
radio4: '',
symptoms: '',
}}
onSubmit={async (values) => {
await new Promise((r) => setTimeout(r, 500));
console.log(JSON.stringify(values, null, 2));
}}
validator={() => ({})}
>
<Form>
<RadioInputGroup
label="Disable the checkbox?"
name="radio4"
options={['Yes','No']}
/>
<CheckboxGroup
{(fields.radio4.value === "yes") ? "disabled" : null}
name="checkbox1"
options={[
{name:"hello",label:"hello"},
{name:"there",label:"there"},
]}
/>
<button type="submit">Submit</button>
</Form>
</Formik>
)
}
I'm not sure the custom components are relevant here but...
const RadioInputGroup = (props) => {
const [field, meta] = useField({...props, type:'radio'});
return (
<FormControl component="fieldset">
<FormLabel component="legend">{props.label}</FormLabel>
<RadioGroup aria-label={props.name} name={props.name} value={props.value}>
<FieldArray name="options">
{({ insert, remove, push }) => (
props.options.length > 0 && props.options.map((option,index) => (
<FormControlLabel key={index} {...props} value={option.toLowerCase()} control={<Radio />} label={option} />
))
)}
</FieldArray>
</RadioGroup>
</FormControl>
)
};
const CheckboxGroup = (props) => {
const [field, meta] = useField({...props, type: 'checkbox', });
return (
<FormControl component="fieldset">
<FormLabel component="legend">{props.label}</FormLabel>
<FormGroup>
<FieldArray name="options">
{({ insert, remove, push}) => (
props.options.length > 0 && props.options.map((option,index) => (
<FormControlLabel
{...field} {...props}
key={index}
control={<Checkbox />}
label={option.label}
/>
))
)}
</FieldArray>
</FormGroup>
<FormHelperText>Be careful</FormHelperText>
</FormControl>
)
}
I wrapped the whole <Form> in a function that passes props as an argument. I then get access to props.values.radio1. However, that has exposed that radio1 does not have a value even when it is clicked, which should be a separate issue.
{(props) => (
<Form>
<RadioInputGroup
label="Disable the checkbox?"
name="radio4"
options={['Yes','No']}
/>
<CheckboxGroup
disabled={props.values.radio1 === "No"}
name="checkbox1"
options={[
{name:"hello",label:"hello"},
{name:"there",label:"there"},
]}
/> </Form>
)}

Formik FieldArray nested object validations with Yup

https://codesandbox.io/s/wonderful-brattain-928gd
Above, I have added some sample code of the problem I am trying to figure out. I am not sure how to map the errors to the correct items in the FieldArray.
In the example, there are yes/no radio buttons which allow a user to indicate whether they have foods they want to add. If they select 'yes', the food options appear and they must select at least 1 of the foods and enter its expiration date to fully validate.
I am trying to add an "expiration" validation error when the users fails to enter an expiration date in the text field. For example, if I select "Beef" and do not enter an expiration date, the errors populate in the Formik errors. However, I don't know how to map that error to the correct expiration text box.
Any help is appreciated!
Note:
Validations are only triggered when the validated button is clicked
There is codesandbox and code shown belown:
<Form>
<pre
style={{
textAlign: "left"
}}
>
<h3>Data</h3>
{JSON.stringify(values, null, 2)}
<h3>Errors</h3>
{JSON.stringify(errors, null, 2)}
</pre>
<Field
name="food.hasFood"
value
type="radio"
onChange={e => {
setFieldValue("food.hasFood", true);
}}
/>{" "}
Yes
<Field
name="food.hasFood"
value={false}
type="radio"
onChange={e => {
setFieldValue("food.hasFood", false);
}}
/>{" "}
No
{values.food.hasFood && (
<FieldArray name="food.selected">
{arrayHelpers => {
return foodTypes.map(item => (
<div key={item}>
<Field
name={item}
value={item}
type="checkbox"
as={Checkbox}
checked={values.food.selected
.map(f => f.name)
.includes(item)}
onChange={e => {
if (e.target.checked) {
arrayHelpers.push({
name: e.target.value,
expiration: ""
});
} else {
const index = values.food.selected
.map(f => f.name)
.indexOf(e.target.value);
arrayHelpers.remove(index);
}
}}
/>
{item}
{errors.food && touched.food && (
<p>
{Array.isArray(errors.food.selected)
? ""
: errors.food.selected}
</p>
)}
{values.food.selected.map((selectedFood, index) => {
if (item === selectedFood.name) {
return (
<div>
<Field
key={index}
as={TextField}
name={`food.selected[${index}].expiration`}
/>
{console.log(errors)}
{errors.food && touched.food && (
<p>
{Array.isArray(errors.food.selected)
? errors.food.selected[index].expiration
: errors.food.selected}
</p>
)}
</div>
);
}
return null;
})}
</div>
));
}}
</FieldArray>
)}
<button
type="button"
onClick={() => {
validateForm();
}}
>
Validate
</button>
</Form>

Categories

Resources