How to have react-datepicker update Formik nested object - reactjs

So I set up datepicker within my form like so
<FieldArray
name="config"
render={(arrayHelpers) => (
<div>
{values.config.map((config, index) => (
<div key={index}>
...
<DatePicker
name={`config.${index}.date`}
type="date"
value={values.date}
className={
"form-control" +
(errors.date&& touched.date
? " is-invalid"
: "")
}
onChange={(e) =>
setFieldValue("date", e)
}
/>
The data is added to the state but as an additional field instead of updating the initial state within formik. It updates likes this.
{"domain_url":"","schema_name":"","name":"","config":[{"first":"","last":"","email":"","date":""}],"date":"2020-06-10T04:00:00.000Z"}
I would appreciate any ideas.
below is a new edit of the majority of the code.
the datepicker is not displaying the date within the form field but it is updating the state correctly, now I just need it to display correctly within the form and format the date to drop the string at the end
static propTypes = {
addTenant: PropTypes.func.isRequired,
};
onSubmit = (values) => {
values.preventDefault();
this.props.addTenant(values);
};
render() {
const {
domain_url,
schema_name,
name,
config,
} = this.state;
const TenantSchema = Yup.object().shape({
domain_url: Yup.string()
.max(255, "Must be shorter than 255 characters")
.required("Client URL header is required"),
schema_name: Yup.string()
.max(255, "Must be shorter than 255 characters")
.required("Client db name is required"),
name: Yup.string()
.max(255, "Must be shorter than 255 characters")
.required("Client name is required"),
});
return (
<div className={s.root}>
<Formik
initialValues={{
domain_url: "",
schema_name: "",
client_name: "",
config: [
{
date: "",
Tenant_description: "",
},
],
}}
// validationSchema={TenantSchema} this is commented off because it breaks
submittions
onSubmit={(values, { setSubmitting, resetForm }) => {
setSubmitting(true);
values.domain_url = values.domain_url + ".localhost";
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
resetForm();
setSubmitting(false);
}, 100);
}}
>
{({
values,
errors,
status,
touched,
handleBlur,
handleChange,
isSubmitting,
setFieldValue,
handleSubmit,
props,
}) => (
<FormGroup>
<Form onSubmit={handleSubmit}>
<legend>
<strong>Create</strong> Tenant
</legend>
<FormGroup row>
<Label for="normal-field" md={4} className="text-md-right">
Show URL
</Label>
<Col md={7}>
<InputGroup>
<Field
id="appended-input"
name="domain_url"
type="text"
value={values.domain_url}
className={
"form-control" +
(errors.domain_url && touched.domain_url
? " is-invalid"
: "")
}
/>
<ErrorMessage
name="domain_url"
component="div"
className="invalid-feedback"
/>
<InputGroupAddon addonType="append">
.localhost
</InputGroupAddon>
</InputGroup>
</Col>
</FormGroup>
<FormGroup row>
<Label for="normal-field" md={4} className="text-md-right">
Database Name
</Label>
<Col md={7}>
<Field
name="schema_name"
type="text"
className={
"form-control" +
(errors.schema_name && touched.schema_name
? " is-invalid"
: "")
}
/>
<ErrorMessage
name="schema_name"
component="div"
className="invalid-feedback"
/>
</Col>
</FormGroup>
<FormGroup row>
<Label for="normal-field" md={4} className="text-md-right">
Name
</Label>
<Col md={7}>
<Field
name="name"
type="text"
className={
"form-control" +
(errors.name && touched.name
? " is-invalid"
: "")
}
/>
<ErrorMessage
name="name"
component="div"
className="invalid-feedback"
/>
</Col>
</FormGroup>
<FieldArray
name="config"
render={(arrayHelpers) => (
<div>
{values.config.map((config, index) => (
<div key={index}>
<FormGroup row>
<Label
md={4}
className="text-md-right"
for="mask-date"
>
Tenant Description
</Label>
<Col md={7}>
<TextareaAutosize
rows={3}
name={`config.${index}.tenant_description`}
id="elastic-textarea"
type="text"
onReset={values.event_description}
placeholder="Quick description of tenant"
onChange={handleChange}
value={values.tenant_description}
onBlur={handleBlur}
className={
`form-control ${s.autogrow} transition-height` +
(errors.tenant_description &&
touched.tenant_description
? " is-invalid"
: "")
}
/>
<ErrorMessage
name="tenant_description"
component="div"
className="invalid-feedback"
/>
</Col>
</FormGroup>
<FormGroup row>
<Label
for="normal-field"
md={4}
className="text-md-right"
>
Date
</Label>
<Col md={7}>
<DatePicker
name={`config[${index}]['date']`}
selected={getIn(values, `config[${index}]
['date']`) || ''}
value={getIn(values, `config[${index}]
['date']`) || ''}
onChange={(e) =>
setFieldValue(`config[${index}]['date']`, e);
}
/>
/>
<ErrorMessage
name="date"
component="div"
className="invalid-feedback"
/>
</Col>
</FormGroup>
</div>
))}
</div>
)}
/>
<div className="form-group">
<button
type="submit"
disabled={isSubmitting}
className="btn btn-primary mr-2"
>
Save Tenant
</button>
<button type="reset" className="btn btn-secondary">
Reset
</button>
</div>
</Form>
<Col md={7}>{JSON.stringify(values)}</Col>
</FormGroup>
)}
</Formik>
</div>
);
}
}
export default connect(null, { addTenant })(TenantForm);

Change your name,value and onChange as following
import { FieldArray, getIn } from 'formik';
<DatePicker
name={`config[${index}]['date']`}
selected={getIn(values, `config[${index}]['date']`) || ''}
value={getIn(values, `config[${index}]['date']`) || ''}
onChange={(e) =>
setFieldValue(`config[${index}]['date']`, e);
}
/>

Related

Populate react formik form with existing data

i am new to react, can anyone explain to me how can i manipulate or repopulate my existing form from backend data in react.
I am trying to edit and existing item in the inventory that i wanna change values for. i am using formik with react and formik grid. for data i am using AXIOS.
What i am trying to do is to get edit a specific entry from my database which has changed values. it's like trying to update values
<Formik
validationSchema={schema}
initialValues={{
name: "",
numberOfSets: "0",
sortValue: "0",
boxType: "",
price: "",
photo: "",
}}
onSubmit={({
name,
numberOfSets,
sortValue,
boxType,
price,
photo,
}) => {
boxService.addBox(
name,
numberOfSets,
sortValue,
boxType,
price,
photo
);
alert("Box added Successfully!"); // Box or Gift it's same thing
window.location.reload(false);
}}
>
{({
values,
errors,
touched,
handleBlur,
handleSubmit,
setFieldValue,
}) => {
return (
<Form
form={form}
name="edit-gift"
onFinish={handleSubmit}
{...layout}
labelAlign="left"
>
// These are the fields i am trying to manipulate
<Form.Item name="name" label="Name">
<Input
name="name"
title="Product Name"
dataIndex="name"
key="productName"
value={values.name}
onChange={(e) => setFieldValue("name", e.target.value)}
onBlur={handleBlur}
placeholder="Please enter Box Name"
/>
{errors?.name && touched?.name && (
<Text type="danger">{errors?.name}</Text>
)}
</Form.Item>
<Form.Item name="numberOfSets" label="Number of Sets">
<Input
name="numberOfSets"
type="number"
value={values.numberOfSets}
onChange={(e) =>
setFieldValue("numberOfSets", e.target.value)
}
onBlur={handleBlur}
placeholder="Please enter Number of Sets"
/>
{errors?.numberOfSets && touched?.numberOfSets && (
<Text type="danger">{errors?.numberOfSets}</Text>
)}
</Form.Item>
<Form.Item name="sortVlaue" label="Sort Value">
<Input
name="sortVlaue"
type="number"
value={values.sortValue}
onChange={(e) => setFieldValue("sortVlaue", e.target.value)}
onBlur={handleBlur}
placeholder="Please enter soring value"
/>
{errors?.numberOfBoxes && touched?.numberOfBoxes && (
<Text type="danger">{errors?.numberOfBoxes}</Text>
)}
</Form.Item>
<Form.Item name="boxType" label="Type">
<Select
value={values.boxType}
onChange={(value) => setFieldValue("boxType", value)}
onBlur={handleBlur}
placeholder="Please enter Box Type"
>
<Select.Option value="reward">Reward</Select.Option>
<Select.Option value="doublerandom">
Double Random
</Select.Option>
</Select>
{errors?.boxType && (
<Text type="danger">{errors?.boxType}</Text>
)}
</Form.Item>
<Form.Item name="price" label="Price">
<Input
name="price"
title="Product Price"
dataIndex="price"
key="price"
value={values.price}
onChange={(e) => setFieldValue("price", e.target.value)}
onBlur={handleBlur}
placeholder="Please enter Box Price"
/>
{errors?.price && touched?.price && (
<Text type="danger">{errors?.price}</Text>
)}
</Form.Item>
<Form.Item name="photo" label="Product Picture">
<div className="dropzone-container">
{values.photo && <img src={values.photo} alt=""></img>}
{!values.photo && (
<Dropzone
onDrop={(acceptedFiles) => {
acceptedFiles.map((file) => {
console.log(file);
});
let fr = new FileReader();
fr.onload = function () {
setFieldValue("photo", fr.result);
setFieldValue("imgName", acceptedFiles[0].name);
console.log(acceptedFiles[0]);
};
fr.readAsDataURL(acceptedFiles[0]);
}}
accept={{ "image/*": [] }}
maxSize={1000000}
>
{({ getRootProps, getInputProps }) => (
<section>
<div {...getRootProps({ style })}>
<input {...getInputProps()} />
<p>
Drag 'n' drop some files here, or click to
select files
</p>
<aside>
Tips: The size ratio of the photo is: 750:216,
the maximum recommended size is 1M, and the
format is: .jpg, .jpeg, .png
</aside>
</div>
</section>
)}
</Dropzone>
)}
</div>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Cofirm save
</Button>
</Form.Item>
</Form>
);
}}
</Formik>
You could either:
rerender the Formik component when your data is available and pass it to the initialValues prop by doing something like
results?.data && <Formik initialValues={{...}}>...</Formik>
or set the values manually with setValues after the data is available
const {setValues, values, ...} = useFormik({...});
useEffect(() => {
setValues(results?.data); // use any fields from your data
}, [results]} // this is the data from your api

React onSubmit are not triggered with some Form.Check checkboxes

I have written modal window with dynamic fields. Text input, date and radio boxes works fine, but when I`m trying to use checkbox inputs it falls.
handleSubmit does not work and not goes into method body
AnswerQuestion:
function AnswerQuestion(props) {
const {questionStore} = useContext(Context);
const dispatch = useNotification();
const question = questionStore.getActiveAnswer();
const show = props.show;
const handleClose = props.handleClose;
const handleUpdate = props.handleUpdate;
const [checkedState, setCheckedState] = useState(question.id && question.answerEntity.answerType === "CHECKBOX"
? Array(question.answerEntity.options.length).fill(false)
: []
)
useEffect(() => {
if(question.id && question.answerEntity.answerType === "CHECKBOX") {
const newCheckedState = question.answerEntity.options.map((option) => question.answerEntity.answer.includes(option));
setCheckedState(newCheckedState);
}
}, [])
const setInitialValues = () => {
if (question.id) {
return {
author: question.author.username,
question: question.question,
answerType: question.answerEntity.answerType,
options: question.answerEntity.options,
date: question.answerEntity.answerType === "DATE" && question.answerEntity.answer ? new Date(question.answerEntity.answer) : new Date(),
answer: question.answerEntity.answer ? question.answerEntity.answer : "",
};
} else {
return {
author: "",
question: "",
answerType: "",
options: "",
date: new Date(),
answer: "",
};
}
};
const schema = yup.object().shape({
author: yup.string().required(),
question: yup.string().required(),
answer: yup.string(),
answerCheckBox: yup.array(),
date: yup.date(),
});
const submit = (values) => {
questionStore
.answerActiveQuestion(question.answerEntity.answerType, values.answer, values.date)
.then(() => handleUpdate());
handleClose();
dispatch({
type: "SUCCESS",
message: "Your answer was saved.",
title: "Success"
})
}
return (
<Formik
enableReinitialize
render={(props) => {
return (
<AnswerQuestionForm
{...props}
show={show}
handleClose={handleClose}
checkedState={checkedState}
></AnswerQuestionForm>
);
}}
initialValues={setInitialValues()}
validationSchema={schema}
onSubmit={submit}
>
</Formik>
)
}
And AnswerQuestionForm:
function AnswerQuestionForm(props) {
const {
values,
errors,
touched,
handleSubmit,
handleChange,
handleClose,
setFieldValue,
setFieldTouched,
show,
checkedState,
} = props;
function insertAnswerModule() {
switch (values.answerType) {
case "DATE":
return (
<Col sm={9}>
<DatePicker
name="date"
value={Date.parse(values.date)}
selected={values.date}
className="form-control"
onChange={(e) => {
setFieldValue('date', e);
setFieldTouched('date');
}}
/>
</Col>
)
case "SINGLE_LINE_TEXT":
return (
<Col sm={9}>
<Form.Control
type="text"
name="answer"
value={values.answer}
onChange={handleChange}
isValid={touched.question && !errors.question}
isInvalid={!!errors.question}
/>
<Form.Control.Feedback type="invalid">
{errors.question}
</Form.Control.Feedback>
</Col>
)
case "MULTILINE_TEXT":
return (
<Col sm={9}>
<Form.Control as="textarea" rows={3}
type="text"
name="answer"
value={values.answer}
onChange={handleChange}
isValid={touched.question && !errors.question}
isInvalid={!!errors.question}
/>
<Form.Control.Feedback type="invalid">
{errors.question}
</Form.Control.Feedback>
</Col>
)
case "CHECKBOX":
return (
<Col sm={9}>
{values.options.map((option, id) => (
<Form.Check
id={id}
type="checkbox"
name="answerCheckBox"
label={option}
value={option}
defaultChecked={checkedState[id]}
onChange={handleChange}
/>
))}
</Col>
)
case "RADIO_BUTTON":
return (
<Col sm={9}>
{values.options.map((option) => (
<Form.Check
type="radio"
name="answer"
label={option}
value={option}
checked={option === values.answer}
onChange={handleChange}
/>
))}
</Col>
)
}
}
return (
<Modal show={show} onHide={handleClose} centered backdrop="static">
<Modal.Header closeButton>
<Modal.Title>Answer the question</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Row className="me-3 md-3 justify-content-between">
<Form.Group as={Row}>
<Form.Label column sm={3}>
From user
</Form.Label>
<Col sm={9}>
<Form.Control
type="text"
name="author"
value={values.author}
readOnly
disabled
></Form.Control>
</Col>
</Form.Group>
</Row>
<Row className="me-3 mt-3 md-3 justify-content-between">
<Form.Group as={Row}>
<Form.Label column sm={3}>
Question
</Form.Label>
<Col sm={9}>
<Form.Control
type="text"
name="question"
value={values.question}
readOnly
disabled
></Form.Control>
</Col>
</Form.Group>
</Row>
<Row className="me-3 mt-3 md-3 justify-content-between">
<Form.Group as={Row}>
<Form.Label column sm={3}></Form.Label>
{insertAnswerModule()}
</Form.Group>
</Row>
</Form>
</Modal.Body>
<Modal.Footer>
<Button variant="primary" onClick={handleSubmit}>
SAVE
</Button>
</Modal.Footer>
</Modal>
)
}
I would be glad to know where is error and how to solve it.
SOLUTION:
I passed answer as string[] if answerType is "CHECKBOX". It`s not allowed in HTML and i changed answer type to string and it begins to work.

react-datetime formik validation

I'm using react-datetime compenent in my react-bootstrap form. Formik with Yup is used for validation.
import React from 'react';
import { Container, Form, Button, Alert, Row, Col, InputGroup } from "react-bootstrap";
import "react-datetime/css/react-datetime.css";
import { Formik} from 'formik';
import * as Icon from 'react-bootstrap-icons';
import * as yup from "yup"
import Datetime from 'react-datetime';
import moment from 'moment';
const validDOB = function( current ){
return current.isBefore(moment());
};
const schema = yup.object().shape({
userId: yup.string().required('Please enter a valid User ID'),
userName: yup.string().required('User\'s Name cannot be empty'),
userDOB: yup.string().required('User\'s Date of Birth cannot be empty'),
});
function AddWorkload(){
return (
<>
<Container>
<Row className="justify-content-md-center">
<h3 style={{textAlign: 'center'}}>Add a New Workload</h3>
<Formik
validationSchema={schema}
onSubmit={console.log}
initialValues={{
userId: '',
userName: '',
userDOB: '',
}}
>
{({
handleSubmit,
handleChange,
handleBlur,
values,
touched,
isValid,
errors,
setFieldValue,
}) => (
<Col md lg="6">
<Form noValidate onSubmit={handleSubmit}>
<Form.Group controlId="userIdInput">
<Form.Label>User ID</Form.Label>
<InputGroup>
<Form.Control
placeholder="User ID"
type="text"
name="userId"
value={values.userId}
onChange={handleChange}
isInvalid={!!errors.userId}
aria-describedby="userIdHelpBlock"
/>
<Button variant="dark"><Icon.Search /> Find User</Button>
<Form.Control.Feedback type="invalid">
{errors.userId}
</Form.Control.Feedback>
</InputGroup>
<Form.Text id="userIdHelpBlock" muted>
Please click "Find User" to fill out the details.
</Form.Text>
</Form.Group>
<Form.Group controlId="userName">
<Form.Label>User Name</Form.Label>
<Form.Control
placeholder="User Name"
type="text"
name="userName"
value={values.userName}
onChange={handleChange}
isInvalid={!!errors.userName}
/>
<Form.Control.Feedback type="invalid">
{errors.userName}
</Form.Control.Feedback>
</Form.Group>
<Form.Group controlId="userDOB">
<Form.Label>Date of Birth</Form.Label>
<Datetime
inputProps={{
placeholder: 'DOB',
id: 'userDOB',
name: 'userDOB',
}}
dateFormat="DD-MM-YYYY"
timeFormat={false}
value={values.userDOB}
isValidDate={validDOB}
onChange={(dateFromValue) => {
setFieldValue('userDOB', dateFromValue);
}
}
isInvalid={!!errors.userDOB}
/>
<Form.Control.Feedback type="invalid">
{errors.userDOB}
</Form.Control.Feedback>
</Form.Group>
<div style={{clear: 'both'}}></div>
<br></br>
<div className='text-center'>
<Button variant="dark" type="reset">Reset Form</Button>{' '}
<Button variant="success" type="submit">Save</Button>
</div>
</Form>
</Col>
)}
</Formik>
</Row>
</Container>
</>
);
}
export default AddWorkload;
Validation for userId and userName is working properly. But I can't get the validation to work for userDOB. I also tried yup.date() but it doesn't work. react-datetime uses moment.js. So, what type to use for the schema and how to get the validation working for that compenent.
Any help would be appreciated.
Thanks
I found my issue. Its because Form.Control.Feedback doesn't correspond to the component Datetime.
So, I removed the Form.Control.Feedback and replaced that with a custom div to display the error message for the Datetime component.
<Form.Group controlId="patientDOB">
<Form.Label>Date of Birth</Form.Label>
<Datetime
inputProps={{
placeholder: 'DD-MM-YYYY',
id: 'userDOB',
name: 'userDOB',
className: formik.errors.userDOB && formik.touched.userDOB ? "form-control is-invalid": "form-control"
}}
closeOnSelect={true}
dateFormat="DD-MM-YYYY"
timeFormat={false}
value={formik.values.userDOB}
isValidDate={validDOB}
onChange={(dateFromValue) => {
formik.setFieldValue('userDOB', moment(dateFromValue).format('DD-MM-YYYY'));
}
}
renderInput={(props) => {
return <input {...props} value={(formik.values.userDOB) ? props.value : ''} />
}}
/>
{formik.errors.userDOB && formik.touched.userDOB ? (
<div className="text-danger" style={{fontSize: '0.875em'}}>{ formik.errors.userDOB }</div>
) : null}
</Form.Group>

focus of field controls with formik

I have a form using formik, comprising a date field and a text field.
when I add a date in the form the text field is automatically put in error.
I think it comes from the initavalues
initialValues={{
comment: '',
endDate: '',
}}
it checks the value of the comment field which is empty and declares it in error.
if I remove comment from initialvalues I end up with an error :
Property 'comment' does not exist on type '{ endDate: string; }'.
How to make so that the field comment is not in error when I empty it or I validate the form?
const FormTest = (props: {
mvts: Movement[];
tiersRef: string;
masterRef: string;
submitCallback: any;
}) => {
const schema = yup.object().shape({
comment: yup.string().required(),
endDate: yup.string().required(),
});
return (
<>
<Formik
initialValues={{
comment: '',
endDate: '',
}}
onSubmit={(values) => {}}
validationSchema={schema}
>
{(formikProps) => (
<form
onSubmit={formikProps.handleSubmit}
aria-label="form-add-promise"
>
<section>
<p>
<I18nWrapper
translateKey={'event.form-create-promise.explanations'}
/>
</p>
</section>
<section>
<Row>
<Form.Group controlId="datePromise" as={Row}>
<Form.Label column lg={6}>
<I18nWrapper
translateKey={'event.form-create-promise.date-promise'}
/>
</Form.Label>
<Col lg={6}>
<Form.Control
value={formikProps.values.comment}
type="date"
name="endDate"
aria-label="from date"
role="date"
onChange={formikProps.handleChange}
isInvalid={!!formikProps.errors.endDate}
/>
<Form.Control.Feedback
type="invalid"
role="alert"
aria-label="no date promise"
>
<FontAwesomeIcon
icon={faTimes}
className="me-2"
size="lg"
/>
<I18nWrapper
translateKey={'event.form-create-promise.error.date'}
/>
</Form.Control.Feedback>
</Col>
</Form.Group>
</Row>
</section>
<section>
<Form.Group controlId="eventComment">
<Form.Label>
<I18nWrapper
translateKey={'event.form-create-promise.error.comment'}
/>
</Form.Label>
<Form.Control
value={formikProps.values.comment}
onChange={formikProps.handleChange}
as="textarea"
aria-label="from textarea"
rows={3}
name="comment"
role="textbox"
isInvalid={!!formikProps.errors.comment}
/>
<Form.Control.Feedback
type="invalid"
role="alert"
aria-label="no comment"
>
<FontAwesomeIcon icon={faTimes} className="me-2" size="lg" />
<I18nWrapper
translateKey={'reminder.modal.phone-reminder.error'}
/>
</Form.Control.Feedback>
</Form.Group>
</section>
<div className="text-center">
<GenericButton
label={'event.form-create-promise.btn-creation'}
type="submit"
disabled={!formikProps.isValid}
/>
</div>
</form>
)}
</Formik>
</>
);
};
export default FormTest;

React Bootstrap Select multiple showing error in Formik as it is expecting a string but returns array

React Bootstrap Select multiple showing error in Formik as it is expecting a string but returns array
Error: Warning: The value prop supplied to must be an array if multiple is true.
Check the render method of FormControl.
I believe that the error is on FormControl.d.ts inside Formik because it only accepts a string as a type
This is the Interface that Formik exposes
export interface FormControlProps {
innerRef?: React.LegacyRef<this>;
size?: 'sm' | 'lg';
plaintext?: boolean;
readOnly?: boolean;
disabled?: boolean;
value?: string; // <-- it should also receive string[] ?
onChange?: React.FormEventHandler<this>;
type?: string;
id?: string;
isValid?: boolean;
isInvalid?: boolean;
}
This is my file from where I'm trying to get the expertise
import React from 'react';
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
import { connect } from 'react-redux';
import { Formik } from 'formik';
import styled from 'styled-components';
import * as Yup from 'yup';
const ExpertSignUpSchema = Yup.object().shape({
expertise: Yup.array()
.of(Yup.string())
.min(1)
.required('Required'),
});
const ExpertSignUpPage: React.FC = () => (
<Container fluid>
<Row>
<Col md={4} />
<Col>
<CardWrapper>
<Card>
<Card.Header as="h5">Expert Registration</Card.Header>
<Card.Body>
<Formik
initialValues={{
expertise: [''],
}}
validationSchema={ExpertSignUpSchema}
onSubmit={(values, { setSubmitting }) => {
console.log(values);
setSubmitting(false);
}}
render={({
values,
errors,
touched,
handleBlur,
handleChange,
handleSubmit,
isSubmitting,
}) => (
<Form noValidate onSubmit={handleSubmit}>
<Form.Control
as="select"
multiple
name="expertise"
onChange={handleChange}
onBlur={handleBlur}
value={values.expertise} // <--- it should allow an array of strings, currently the code won't compile or won't update the form value as it has multiple in the form control
isValid={touched.expertise && !errors.expertise}
isInvalid={!!errors.expertise}
>
<option value="YOGA">Yoga</option>
<option value="PERSONAL_TRAINER">Personal Trainer</option>
<option value="LIFE_COACH">Life Coach</option>
<option value="NUTRITIONIST">Nutritionist</option>
</Form.Control>
</Form.Group>
<Button
variant="outline-primary"
type="submit"
block={true}
disabled={isSubmitting}
>
Register
</Button>
</Form>
)}
/>
</Card.Body>
</Card>
</CardWrapper>
</Col>
<Col md={4} />
</Row>
</Container>
);
export default connect(
null,
null,
)(ExpertSignUpPage);
const CardWrapper = styled.div`
margin-top: 5rem;
`;
For some reason I'm unable to even get the values in the array when I update the the definition file to string | string[].
It took two days to make it error-free... and I had hoped this would be work at your end..
import React from 'react';
import { Container, Row, Col, Image, Form, Button } from 'react-bootstrap';
import style from '../styles/Contact.module.css';
import { Formik, Field} from 'formik';
import * as Yup from 'yup';
const dropdown=[
{
key:"Select an option",
value:""
},
{
key:"Option 1",
value:"option1"
},
{
key:"Option 2",
value:"option2"
},
{
key:"Option 3",
value:"option3"
}
]
// RegEx for phone number validation
const phoneRegExp = /^(\+?\d{0,4})?\s?-?\s?(\(?\d{3}\)?)\s?-?\s?(\(?\d{3}\)?)\s?-?\s?(\(?\d{4}\)?)?$/
// Schema for yup
const validationSchema = Yup.object().shape({
name: Yup.string()
.min(2, "*Names must have at least 2 characters")
.max(30, "*Names can't be longer than 30 characters")
.required("*Name is required"),
email: Yup.string()
.email("*Must be a valid email address")
.max(100, "*Email must be less than 100 characters")
.required("*Email is required"),
phone: Yup.string()
.min(10, "*Names can't be longer than 10 numbers")
.matches(phoneRegExp, "*Phone number is not valid")
.required("*Phone number required"),
msg: Yup.string()
.min(2, "*Messages must have at least 2 characters")
.max(250, "*Messages can't be longer than 250 characters")
.required("*Messages is required"),
selectionOption: Yup.string()
// .of(Yup.string())
// .min(1)
.required('Required'),
});
const Signup = () => {
return (
<>
<Formik
initialValues={{ name: "", email: "", phone: "", msg: "",selectionOption:"" }}
validationSchema={validationSchema}
onSubmit={(values, { setSubmitting, resetForm }) => {
// When button submits form and form is in the process of submitting, submit button is disabled
console.log(values)
setSubmitting(true);
// Simulate submitting to database, shows us values submitted, resets form
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
resetForm();
setSubmitting(false);
}, 500);
}}
>
{({ values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting }) => (
<Form className="form" onSubmit={handleSubmit} autoComplete="off" name="contact" method="POST" >
<Row className="mb-5">
<Col lg={6} md={6} sm={12}>
<Form.Group controlId="formName">
<Form.Label className="form_label" >FullName</Form.Label>
<Form.Control
type="text"
name="name"
placeholder="Full Name"
onChange={handleChange}
onBlur={handleBlur}
value={values.name}
className={touched.name && errors.name ? "has-error" : null}
/>
{touched.name && errors.name ? (
<div className="error-message">{errors.name}</div>
) : null}
</Form.Group>
</Col>
<Col lg={6} md={6} sm={12}>
<Form.Group>
<Form.Label className="form_label" >Number</Form.Label>
<Form.Control
type="text"
name="phone"
placeholder="Phone"
onChange={handleChange}
onBlur={handleBlur}
value={values.phone}
className={touched.phone && errors.phone ? "has-error" : null}
/>
{touched.phone && errors.phone ? (
<div className="error-message">{errors.phone}</div>
) : null}
</Form.Group>
</Col>
</Row>
<Row className="mb-5">
<Col lg={6} md={6} sm={12}>
<Form.Group>
<Form.Label className="form_label" >Email</Form.Label>
<Form.Control
type="text"
name="email"
placeholder="Email"
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
className={touched.email && errors.email ? "has-error" : null}
/>
{touched.email && errors.email ? (
<div className="error-message">{errors.email}</div>
) : null}
</Form.Group>
</Col>
<Col lg={6} md={6} sm={12}>
{/* <Form.Select aria-label="Default select example">
<option>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</Form.Select> */}
<Form.Group controlId="exampleForm.ControlSelect1">
<Form.Label>Example select</Form.Label>
<Form.Control as="select" name ="selectionOption" onChange={handleChange}
onBlur={handleBlur} value={values.selectionOption}
className={touched.selectionOption && errors.selectionOption ? "has-error" : null}
>
{
dropdown.map(drop=>{return(
<option key={drop.value} value={drop.value}>
{drop.key}
</option>
)
}
)
}
</Form.Control>
{/* <ErrorMessage name="selectionOption"></ErrorMessage> */}
{touched.selectionOption && errors.selectionOption ? (
<div className="error-message">{errors.selectionOption}</div>
) : null}
{/* <Form.Label>Example select</Form.Label>
<Field as="select" name ="selectionOption" onChange={handleChange}
onBlur={handleBlur} value={values.selectionOption}
style={{ display: "block" }}
// isValid={touched.selectionOption && !errors.selectionOption}
// isInvalid={!errors.selectionOption}
className={touched.selectionOption && errors.selectionOption ? "has-error" : null}
>
<option className='text-muted'>---</option>
<option value="ortho">ortho</option>
<option value="pedri">pedri</option>
<option value="crown">crown</option>
</Field>
{touched.selectionOption && errors.selectionOption ? (
<div className="error-message">{errors.selectionOption}</div>
) : null} */}
</Form.Group>
</Col>
</Row>
<Row className="mb-5">
<Col lg={12} md={12} sm={12}>
<Form.Group controlId="formmsg">
<Form.Label>Messages :</Form.Label>
<Form.Control
type="text"
name="msg"
as="textarea" rows={4}
placeholder="Query / Feedback"
onChange={handleChange}
onBlur={handleBlur}
value={values.msg}
className={touched.msg && errors.msg ? "has-error" : null}
/>
{touched.msg && errors.msg ? (
<div className="error-message">{errors.msg}</div>
) : null}
</Form.Group>
</Col>
</Row>
<Button type="submit" className={style.customizeBtn} name="contact" id="contact" disabled={isSubmitting}>
<Image src="img/send.png" className={style.imgBtn} />
<span className={style.titleBtn}>Submit</span>
</Button>
</Form>
)}
</Formik>
</>
)
}
export default Signup;

Resources