How to submit a formik form with two similar fields - reactjs

I have a form and on this form there is an Add another form button which adds another form with the same field. I am using fieldArray by formik. Currently if I add another form then submit it's only submitting the values of the first form not the second. How can I ensure that all the form index fields are submitted.
Here's the code
const initialValues = {
certificationItems: [
{
name: '',
description: '',
additionalDetails: '',
isThirdParty: thirdParty,
issueDate: '',
expirationDate: '',
properties: [
{ name: 'prefillCertification', value: '' },
{ name: 'prefillInfo', value: '' }
]
}
]
};
<Formik
initialValues={initialValues}
onSubmit={(values) => {
console.log('values', index)
operations.updateBinding(['name'], values.certificationItems[0].name);
operations.updateBinding(['description'], values.certificationItems[0].description);
operations.updateBinding(['additionalDetails'], values.certificationItems[0].additionalDetails);
operations.updateBinding(['isThirdParty'], values.certificationItems[0].isThirdParty);
operations.updateBinding(['issueDate'], values.certificationItems[0].issueDate);
operations.updateBinding(['expirationDate'], values.certificationItems[0].expirationDate);
operations.submit();
}}

Related

Select option value returns '[object Object]'

I would like to ask for your help. I have mapped a list of data patientOptions to select field, each option has a value of
value: {
id: patient.id,
firstName: patient.firstName,
middleName: patient.middleName,
lastName: patient.lastName,
},
I need to store this information when I submit the form. If I console.log(patientOptions) this will appear
What I am trying to achieve is to get all values
value: {
id: 13412341234,
firstName: John,
middleName: Made,
lastName: Doe,
},
But if I will try to submit the form and log it to the console this will show up.
I have also tried just getting the value of 1 object it works but trying to get the value of multiple objects still returns the same error
Here is the rest of the code I hope anyone can help me.
const patientOptions = patient.map((patient) => ({
key: `${patient.firstName} ${patient.middleName} ${patient.lastName},
value: {
id: patient.id,
firstName: patient.firstName,
middleName: patient.middleName,
lastName: patient.lastName,
},
}));
onSubmit = (values) =>
console.log("form data", {
patient: values.patient,
});
<Formik
initialValues={{
patient: "",
}}
onSubmit={onSubmit}
>
<Form>
<FormikControl
control="select"
name="patient"
label="Patient"
options={patientOptions}
/>
</Form>
</Formik>;

How to use Formik with React-Select with isMulti?

I'm building a system where we can create a project and assign it to several users by filling up a form using Formik, Yup and React-Select.
However, I'm really struggling with passing the array of users when submitting my form using Formik, Formik doesn't receive the data from React-Select.
Here are snippets of the code:
const validationSchema = () => {
return Yup.object().shape({
title: Yup.string().required('A title is required'),
description: Yup.string().required('A description is required'),
assigned: Yup.array().required('At least one assigned user is required'),
});
};
const formik = useFormik({
initialValues: {
title: '',
description: '',
assigned: [],
},
validationSchema,
validateOnBlur: false,
validateOnChange: false,
onSubmit: (data) => {
ProjectService.create(data).then(() => {
navigate('/projects');
window.location.reload();
});
},
});
The component containing the options to select:
Assign to:
<SelectList
name="users"
options={convertToReactSelectObject(users)}
onChange={(assignedUsers) =>
formik.setFieldValue('assigned', assignedUsers.value)
}
value={formik.values.assigned}
/>
{formik.errors.assigned ? formik.errors.assigned : null}
Does someone have an idea of what I should fix to make it work?
Thank you!
My mistake was that I was trying to only pass the "value" field of the array to Formik which doesn't work. So I've passed the whole array of assigned users
<SelectList
options={convertToReactSelectObject(users)}
value={formik.values.assigned}
onChange={(assignedUser) =>
formik.setFieldValue('assigned', assignedUser)
}
/>
Then on the backend, the new project will only take the value field of the assigned users.
// Create a Project
const project = new Project({
title: req.body.title,
description: req.body.description,
assigned: req.body.assigned.map((e) => e.value),
});

form.map is not a function error, only appearing after getting data from an input field

I am trying to get data from input fields and add the values to a list to send as a post request.
I have a form object
const [form, setForm] = useState([
{
hole1: 1,
par1: '',
stroke1: '',
yards1: ''
},
{
hole2: 2,
par2: '',
stroke2: '',
yards2: ''
},
//repeat for 18 holes
Then when I click the submit button after filling in the form,
const list = form.map((holes, i) => {
const num = i +1;
return {
hole: num,
par: holes[`par${num}`],
stroke: holes[`stroke${num}`],
yards: holes[`yards${num}`],
course: {
courseid: 3,
},
};
});
If the form is empty this works fine and if I log the list
0: {hole: 1, par: '', stroke: '', yards: '', course: {…}}
1: {hole: 2, par: '', stroke: '', yards: '', course: {…}}
2: {hole: 3, par: '', stroke: '', yards: '', course: {…}}
As soon as I enter some values into the form though, I get the error Uncaught TypeError: form.map is not a function
I understand form needs to be an array to use the map function, but I cannot figure out why it is working when the form is empty, but as soon as I add data it breaks? Is the data type changing when I add data?
edit,
Code for my onChange method which sets the values in the form.
const onChange = (event) => {
const { value, name } = event.target;
setForm((previousForm) => {
return {
...previousForm,
[name]: value
};
});
setErrors((previousErrors) => {
return {
...previousErrors,
[name]: undefined
};
});
};

how to multiple validation in form with react hook

I have a useState problem, I am trying to add an object in the state but value errors, console.log(errors):
{name: "", description: "", price: "", category: "", image: "Image cannot be empty"}
I want all values ​​in one object.
Hope everyone will help me because I am new.
Here is my code:
const [errors, setErrors] = useState({
name: '',
description: '',
price: '',
category: '',
image: '',
});
const [formIsValid, setFormIsValid] = useState(true);
const handleValidation = () => {
//Name
if(!formState.name){
setFormIsValid(false);
setErrors({
...errors,
name: 'Name cannot be empty',
});
}
//category
if(!formCategory.category){
setFormIsValid(false);
setErrors({
...errors,
category: 'Category cannot be empty',
});
}
//Image
if(!image.image){
setFormIsValid(false);
setErrors({
...errors,
image: 'Image cannot be empty',
});
}
return formIsValid;
};
You are trying to make state update based on your previous state. Basically the issue is following:
you want to make few state updates synchronously (when few properties are not valid) and only last update is applied.
So why this happen?
In the code above when errors is equal to initial state and all fields are empty will happen following
setErrors({
...errors,
name: 'Name cannot be empty',
});
is the same as
setErrors({
description: '',
price: '',
category: '',
image: '',
name: 'Name cannot be empty',
});
after that you are entering another if statement and there you are performing another setState operation with the same state, and errors array gone be the same
so this
setErrors({
...errors,
category: 'Category cannot be empty',
});
will be transformed to this
setErrors({
description: '',
price: '',
category: 'Category cannot be empty',
image: '',
name: '',
});
React will schedule all the setState one after each other and as you are assigning object it will just override the last existing one and name property will be cleared.
So it is two way to solve current issue if you want to use object as a state:
Generate object and then execute setState one time with combined object, that contains all the changes:
const [errors, setErrors] = useState({
name: '',
description: '',
price: '',
category: '',
image: '',
});
const handleValidation = () => {
const newErrorsState = {...errors};
let formIsValid = true;
//Name
if(!formState.name){
formIsValid = false;
newErrorsState.name = 'Name cannot be empty';
}
//category
if(!formCategory.category){
formIsValid = false;
newErrorsState.category = 'Category cannot be empty';
}
//Image
if(!image.image){
formIsValid = false;
newErrorsState.image = 'Image cannot be empty';
}
if (!formIsValid) { // if any field is invalid - then we need to update our state
setFormIsValid(false);
setErrors(newErrorsState);
}
return formIsValid;
};
Second way to solve this issue is to use another way to set your state,
You can use function inside of your setState handler. Inside that function you will receive the latest state as parameter and that state will have latest changes.
More information can be found by the link
const [errors, setErrors] = useState({
name: '',
description: '',
price: '',
category: '',
image: '',
});
const [formIsValid, setFormIsValid] = useState(true);
const handleValidation = () => {
//Name
if(!formState.name){
setFormIsValid(false);
const updateNameFunction = (latestState) => {
return {
...latestState,
name: 'Name cannot be empty',
};
}
setErrors(updateNameFunction);
}
//category
if(!formCategory.category){
setFormIsValid(false);
setErrors((prevErrors) => {
return {
...prevErrors,
category: 'Category cannot be empty',
}
});
}
//Image
if(!image.image){
setFormIsValid(false);
setErrors((prevErrors) => {
return {
...errors,
image: 'Image cannot be empty',
};
});
}
return formIsValid;
};
Not sure what you are trying to achieve.
Anyway I think you want to validate multiple fields and get their errors together.
Please look at react-hook-form documentation
Every field that registered to the form will give you his errors "automatically".
In addition, You can add validations in the object of the second argument of register like that :
<Input {...register("firstName", { required: true })} />
List of available validations that you can add
Hope thats help you :) Good luck!
from where formState is coming? and you can use usereducer or react-hook-form library for better approch

Unable to validate number in React with Bootstrap

I am trying to validate an HTML-Input field rendered with React to only accept numbers. My current attempt to do that.
What must be done in order to validate the Input field to only accept numbers?
phone: {
elementLabel: 'Phone Number',
elementType: 'input',
elementConfig: {
type: "number",
placeholder: 'Phone Number',
name: "phone",
id: "phone",
min: "0",
pattern: "[0-9]*",
},
value: '',
form_value: "",
validation: {},
valid: false,
touched: false,
className: "form-control",
changed: (event) => this.inputChangedHandler(event,
"phone"),
blured: (event) => this.inputBlurHandler(event,
"phone")
},
render(){
<div>
<Input {...this.state.name}/>
</div>
}
inputChangedHandler = (event, inputIdentifier) => {
const updatedForm = {
...this.state
};
const updatedFormElement = {
...this.state[inputIdentifier]
};
Utils.updateElementValue(updatedFormElement, event, inputIdentifier);
updatedFormElement.touched = true;
updatedForm[inputIdentifier] = updatedFormElement;
let formIsValid = true;
for (let inputIdentifier in updatedForm) {
if (updatedForm[inputIdentifier].elementType) {
formIsValid = updatedForm[inputIdentifier].valid && formIsValid;
}
}
this.setState({ [inputIdentifier]: updatedFormElement, formIsValid: formIsValid });
}
Also this is my change handler looks like
Number is not validated when taking input from the control. While using this, I want validaiton that only input numbers, not even any special characters.
Edit 1:
I use the following versions:
bootstrap: ^4.3.1
react: ^16.8.6
I think the pattern you are using is wrong. It should be ^[0-9]*$ which accepts any number of digits, including none.

Resources