React picky not auto closing while selecting one value,? - reactjs

If using single select, is it possible to close the dropdown after selection? I tried passing keepOpen props but cant able to fix, whiling passing keepOpen the drop down not working as it would, How can fix this issue?
console log while clicking drop down
console log
Parent Component Input Feild
<Grid item xs={12} sm={12} md={12} className={classes.item}>
<Field name='gender' label={I18n.t('gender')} filterable={false} component={renderSelect} >
{
_.get(getGender, 'data', genderArray)
}
</Field>
</Grid>
<Grid item xs={12} sm={12} md={12} className={classes.item}>
<Field name='userTypeResponse' label={I18n.t('user_type')} component={renderSelect} filterable={false} >
{
data?.map(item => ({ id: item.id, name: item.name }))
}
</Field>
</Grid>
Selector Component
const renderSelect = ({ input: { value, name, ...inputProps }, children, selectAll, selectAllText = 'Select All', filterable = true, multiple, label, disabled = false, placeholder = '', showLoader = false, spinnerProps = 'selectTagProp', meta: { touched, error } }) => {
return < LoadingOverlay active={showLoader} spinnerProps={spinnerProps} >
<FormGroup>
{label && <div className='customPicky'>
<InputLabel htmlFor={name}>{label}</InputLabel>
</div>}
<MultiSelect
value={multiple ? value || [] : value || null} {...inputProps}
options={children}
open={false}
multiple={multiple}
keepOpen={false}
includeSelectAll={selectAll}
selectAllText={selectAllText}
includeFilter={filterable}
labelKey='name'
valueKey='id'
placeholder={placeholder}
dropdownHeight={150}
clearFilterOnClose={true}
defaultFocusFilter={true}
disabled={disabled}
className={disabled === true ? 'pickySelect grey' : null}
numberDisplayed={1}
renderList={({ items, selectValue, getIsSelected }) => {
return <div >
{items.length < 1 && <div style={{ textAlign: 'center', padding: '5px' }}>{I18n.t('no_data_available')}</div>}
{items.map(item => (
<li key={item.id} onClick={() => selectValue(item)} style={{ display: 'flex', alignItems: 'center' }}>
<input type={multiple ? 'checkbox' : 'radio'} id={item.id} checked={getIsSelected(item)} />
<div style={{ marginLeft: '5px' }} >
{item.name}
</div>
</li>
))}
</div>;
}
}
/>
{touched && error && <Typography color="error" variant="caption">{error}</Typography>}
</FormGroup>
</LoadingOverlay >;
};

Related

How to stop modal from closing when clicking on a select option?

I've made a custom filter for MUI's datagrid, the filter has two select's which allow you to filter by the column and filter type. The selects are quite big and endup outside the modal, when clicking on an option the whole modal closes, how can I prevent this from happening?
I've used this tutorial - Detect click outside React component to detect clicks outside the filter.
The code below shows the filter and I've also made an codesandbox example here - https://codesandbox.io/s/awesome-panka-g92vhn?file=/src/DataGridCustomFilter.js:0-6708
any help would be appreciated
import React, { useState, useEffect, useRef } from "react";
import {
Button,
Stack,
FormControl,
InputLabel,
Select,
MenuItem,
Paper,
Grid,
IconButton,
TextField,
ClickAwayListener
} from "#material-ui/core";
import FilterListIcon from "#mui/icons-material/FilterList";
import AddIcon from "#mui/icons-material/Add";
import CloseIcon from "#mui/icons-material/Close";
import { useForm, useFieldArray, Controller } from "react-hook-form";
import { columns } from "./columns";
const filterTypes = {
string: ["contains", "equals", "starts with", "ends with", "is any of"],
int: ["contains", "equals", "less than", "greater than"]
};
function FilterRow({
len,
setOpen,
field,
control,
columns,
index,
handleRemoveFilter
}) {
return (
<Grid container spacing={0}>
<Grid
item
md={1}
style={{
display: "flex",
alignSelf: "flex-end",
alignItems: "center"
}}
>
<IconButton
size="small"
onClick={() => {
if (len === 1) {
setOpen(false);
} else {
console.log(index, "---");
handleRemoveFilter(index);
}
}}
>
<CloseIcon style={{ fontSize: "20px" }} />
</IconButton>
</Grid>
<Grid item md={4}>
<Controller
name={`filterForm.${index}.column`}
control={control}
render={({ field: { onChange, value }, fieldState: { error } }) => (
<FormControl variant="standard" sx={{ width: "100%" }}>
<InputLabel>Column</InputLabel>
<Select
value={value}
onChange={onChange}
label="Column"
defaultValue=""
>
{columns.map((a) => {
return a.exclude_filter === true ? null : (
<MenuItem value={a.headerName}>{a.headerName}</MenuItem>
);
})}
</Select>
</FormControl>
)}
/>
</Grid>
<Grid item md={3}>
<Controller
name={`filterForm.${index}.filter`}
control={control}
render={({ field: { onChange, value }, fieldState: { error } }) => (
<FormControl variant="standard" sx={{ width: "100%" }}>
<InputLabel>Filter</InputLabel>
<Select
value={value}
onChange={onChange}
label="Filter"
defaultValue=""
>
{filterTypes.string.map((a) => {
return <MenuItem value={a}>{a}</MenuItem>;
})}
</Select>
</FormControl>
)}
/>
</Grid>
<Grid item md={4}>
<Controller
name={`filterForm.${index}.value`}
control={control}
render={({ field: { onChange, value }, fieldState: { error } }) => (
<FormControl>
<TextField
onChange={onChange}
value={value}
label="Value"
variant="standard"
/>
</FormControl>
)}
/>
{/* )} */}
</Grid>
</Grid>
);
}
function DataGridCustomFilter() {
const { control, handleSubmit } = useForm();
const { fields, append, remove } = useFieldArray({
control,
name: "filterForm"
});
const [open, setOpen] = useState(false);
const onSubmit = (data) => {};
useEffect(() => {
if (fields.length === 0) {
append({
column: "ID",
filter: filterTypes.string[0],
value: ""
});
}
}, [fields]);
const [clickedOutside, setClickedOutside] = useState(false);
const myRef = useRef();
const handleClickOutside = (e) => {
if (myRef.current && !myRef.current.contains(e.target)) {
setClickedOutside(true);
setOpen(!open);
}
};
useEffect(() => {
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
});
return (
<>
<Button
startIcon={<FilterListIcon />}
size="small"
onClick={() => {
setOpen(!open);
}}
// disabled={isDisabled}
>
FILTERS
</Button>
{open ? (
<div ref={myRef}>
<Paper
style={{
width: 550,
padding: 10,
zIndex: 1300,
position: "absolute",
inset: "0px auto auto 0px",
margin: 0,
display: "block"
// transform: "translate3d(160.556px, 252.222px, 0px)",
}}
variant="elevation"
elevation={5}
>
<form onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={0.5}>
<div style={{ maxHeight: 210, overflow: "scroll" }}>
{fields.map((field, index) => {
return (
<div style={{ paddingBottom: 5 }}>
<FilterRow
len={fields.length}
control={control}
setOpen={setOpen}
field={field}
columns={columns}
handleRemoveFilter={() => remove(index)}
{...{ control, index, field }}
// handleClickAway={handleClickAway}
/>
</div>
);
})}
</div>
<div style={{ marginTop: 10, paddingLeft: 40 }}>
<Stack direction="row" spacing={1}>
<Button size="small" startIcon={<AddIcon />}>
ADD FILTER
</Button>
<Button size="small" type="submit">
{fields.length > 1 ? "APPLY FILTERS" : "APPLY FILTER"}
</Button>
</Stack>
</div>
</Stack>
</form>
</Paper>
</div>
) : null}
</>
);
}
export default DataGridCustomFilter;
So far I've tried MUI's ClickAwayListener and the example above, both seem to give the same result
DataGrid component uses NativeSelect. I have checked your codesandbox and tried replacing Select to NativeSelect and MenuItem to Option. filter is working properly. below is sample code for update.
...
<NativeSelect
value={value}
onChange={onChange}
label="Column"
defaultValue=""
>
{columns.map((a) => {
return a.exclude_filter === true ? null : (
<option value={a.headerName}>{a.headerName}</option >
);
})}
</NativeSelect>
...

How to use react autocomplete package to select users from input in React

i am using https://www.npmjs.com/package/react-search-autocomplete package to select users from input field but it is not displaying the results. can any one help what is wrong with my code ?
const Home = ({socket, username, onlineUsers}) => {
const [message, setMessage] = useState("");
const handleSubmitMessage =(e)=> {
e.preventDefault();
const newMessage = {
text: message,
sender: username,
id: socket.id,
timeStamp: Date.now()
}
socket.emit("sendmessage", newMessage)
}
const handleOnSearch = (string, results) => {
// onSearch will have as the first callback parameter
// the string searched and for the second the results.
console.log(string, results)
}
const handleOnHover = (result) => {
// the item hovered
console.log(result)
}
const handleOnSelect = (item) => {
// the item selected
console.log("ITEM",item)
}
const handleOnFocus = () => {
console.log('Focused')
}
const formatResult = (item) => {
return (
<>
<span style={{ display: 'block', textAlign: 'left' }}>name: {item.name}</span>
</>
)
}
return (
<Container fluid className="px-4">
<Row className="my-3 d-flex justify-content-center" style={{ height: "95vh" }}>
<Col md={6} className="p-4 d-flex flex-column justify-content-between chat-container">
{/* USERNAME INPUT */}
<div style={{ width: 400 }}>
<ReactSearchAutocomplete
items={onlineUsers}
onSearch={handleOnSearch}
onHover={handleOnHover}
onSelect={handleOnSelect}
onFocus={handleOnFocus}
autoFocus
formatResult={formatResult}
/>
</div>
{/* MESSAGE BOX */}
<ListGroup >
<ListGroup.Item className="message-input">Cras justo odio</ListGroup.Item>
</ListGroup>
{/* NEW MESSAGE INPUT */}
<Form className="d-flex" >
<Form.Control
className="inputs rounded-pill"
type="text"
placeholder="What is your message ?"
value={message}
onChange={(e) => setMessage(e.target.value)}
/>
<BiSend className="text-info" style={{fontSize:"39px"}} onClick={handleSubmitMessage}/>
</Form>
</Col>
</Row>
</Container>
);
Here is my onlineUsers object. When i use react-autocomplete package default data it is working but with this object did not work
[
{
"username": "Asd",
"id": "BB-z5RFducnJ029xAAAX"
}
]
By default the search will be done on the property "name" but you have username instead, to change this behavior, change the fuseOptions prop. and that the component uses the key "name" in your items list to display the result. but your list of items does not have a "name" key, use resultStringKeyName to tell what key ('username') to use to display in the results.
just change :
<span style={{ display: 'block', textAlign: 'left' }}>name: {item.name}</span>
to :
<span style={{ display: 'block', textAlign: 'left' }}>name: {item.username}</span>
and change :
<ReactSearchAutocomplete
items={onlineUsers}
onSearch={handleOnSearch}
onHover={handleOnHover}
onSelect={handleOnSelect}
onFocus={handleOnFocus}
autoFocus
formatResult={formatResult}
/>
to :
<ReactSearchAutocomplete
fuseOptions={{ keys: ["username"] }}
resultStringKeyName="username"
items={onlineUsers}
onSearch={handleOnSearch}
onHover={handleOnHover}
onSelect={handleOnSelect}
onFocus={handleOnFocus}
autoFocus
formatResult={formatResult}
/>
this is a demo in codesandbox

Uncheck the parent checkbox on unchecking child elements in React App

I have a check for Select All to check all/Uncheck all the child elements but when I uncheck any of the child elements I want to uncheck the parent checkbox as well.
I can check and uncheck all when I select the SELECT ALL, but cannot achieve vice versa when any of the child element is unchecked.
export const List = props => {
const{startOver} = props;
const onCheckAllcheckbox = (event) => {
let _items = props.items.map(item => {
item.isChecked = event.target.checked
return item;
});
props.setItems(_items);
}
const handleCheckChieldElement = (event) => {
let _items = props.items.map(item => {
if (item.id == event.target.value) {
item.isChecked = event.target.checked
}
return item;
})
props.setItems(_items);
}
return (
<Box>
{props.action && (
<Box horizontal align="center">
<input type="checkbox"
onChange={onCheckAllcheckbox}
defaultChecked={true}
style={{width: '20px', height: '15px'}} />
<Text>SELECT ALL</Text>
</Box>
)}
<div style={{overflow : 'auto', height : '200px', width : '900'}}>
<Box type="flat">
{props.items.map((item, index) => (
<Box key={index} horizontal align="center" style={{ margin: '.3rem 0' }}>
{props.action && (
<input type="checkbox"
onChange={handleCheckChieldElement}
checked={item.isChecked}
value={item.id}
style={{width: '20px', height: '15px'}} />
)}
{props.itemTemplate && props.itemTemplate(item) || (
<Text>{item.text}</Text>
)}
</Box>
))}
</Box>
</div>
</Box>
)
}
Add checked attribute to Select All input instead of passing defaultChecked attribute.
<Box horizontal align="center">
<input type="checkbox"
onChange={onCheckAllcheckbox}
checked={props.items.every((item) => item.isChecked)}
style={{width: '20px', height: '15px'}} />
<Text>SELECT ALL</Text>
</Box>

Handling Multiple Checkboxes with Material UI and Formik

I have a form with a checkbox group containing 4 checkboxes within. I need to pass the value to my api on submit of button which is to be handled through Formik.
There are a few conditions on clicking a particular checkbox:
If Height is checked, rest all should be checked as well
If Breadth is checked, except for Height all should be checked
If Length is checked, Both Nos and Length should be checked
Nos can be checked or left unchecked
Currently I'm declaring individual states for all checkboxes and declaring individual functions for each of the conditions mentioned above.
Is there any other way to bind the values from the checkbox to Formik and pass to the api
State and Individual Functions:
const [nos, setNos] = useState(false);
const [length, setLength] = useState(false);
const [breadth, setBreadth] = useState(false);
const [height, setHeight] = useState(false);
const handleHeight = e => {
setNos(!nos);
setLength(!length);
setBreadth(!breadth);
setHeight(!height);
};
const handleBreadth = e => {
setNos(!nos);
setLength(!length);
setBreadth(!breadth);
};
const handleLength = e => {
setNos(!nos);
setLength(!length);
};
const handleNos = e =>{
setNos(!nos);
};
Form with Formik:
const formik = useFormik({
initialValues,
validationSchema,
onSubmit: async (values) => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<>
<form
onKeyDown={onKeyDown}
id="newJobDetails"
name="newJobDetails"
onSubmit={formik.handleSubmit}
className={CommonClasses.formPartStyling}
style={{
height: SetFormSize(
isAdd ? "Add" : textFieldDisable ? "Info" : "Edit",
1
),
marginTop: marginTop || "none",
}}
>
<div
className={CommonClasses.headingTextOfForms}
style={{ marginLeft: "4%", marginTop: "2%" }}
>
Add Jobs
</div>
<Divider
style={{
marginTop: "1%",
marginBottom: "3%",
color: "white",
}}
></Divider>
<div
style={{
marginLeft: "4%",
marginTop: "2%",
}}
>
<Grid container>
<Grid item xs={6}>
<LabelStyling>Job Name</LabelStyling>
<TextField
id="jobName"
name="jobName"
variant="outlined"
placeholder="Enter Job Name"
value={formik.values.jobName}
onChange={formik.handleChange}
size="small"
style={{
width: FORM_PART_VARS.INPUT_BOX_WIDTH,
}}
/>
</Grid>
<Grid item xs={6}>
<LabelStyling>Stage</LabelStyling>
<DropDown
id="stage"
width={FORM_PART_VARS.INPUT_BOX_WIDTH}
value={formik.values.stage}
onChange={formik.handleChange}
error={formik.touched.stage && Boolean(formik.errors.stage)}
helperText={formik.touched.stage && formik.errors.stage}
mapFile={Stage}
placeholder="Select Stage"
/>
</Grid>
</Grid>
</div>
<div
style={{
marginLeft: "4%",
marginTop: "2%",
}}
>
<Grid container>
<Grid item xs={6}>
<LabelStyling>Measurement</LabelStyling>
<TextField
id="measurement"
name="measurement"
variant="outlined"
placeholder="Enter Measurement"
value={formik.values.measurement}
onChange={formik.handleChange}
size="small"
style={{
width: FORM_PART_VARS.INPUT_BOX_WIDTH,
}}
/>
</Grid>
<Grid item xs={6}>
<LabelStyling>Measurement Unit</LabelStyling>
<DropDown
id="measurement_unit"
width={FORM_PART_VARS.INPUT_BOX_WIDTH}
value={formik.values.measurement_unit}
onChange={formik.handleChange}
error={
formik.touched.measurement_unit &&
Boolean(formik.errors.measurement_unit)
}
helperText={
formik.touched.measurement_unit &&
formik.errors.measurement_unit
}
mapFile={MeasurementUnit}
placeholder="Select Unit"
/>
</Grid>
</Grid>
</div>
<div
style={{
marginLeft: "4%",
marginTop: "2%",
}}
>
<Grid container>
<Grid item xs={6}>
<LabelStyling>Rate</LabelStyling>
<TextField
name="jobRate"
id="jobRate"
variant="outlined"
placeholder="Enter Rate"
value={formik.values.jobRate}
onChange={formik.handleChange}
size="small"
style={{
width: FORM_PART_VARS.INPUT_BOX_WIDTH,
}}
/>
</Grid>
<Grid item xs={6}>
<LabelStyling>Service Rate</LabelStyling>
<TextField
name="serviceRate"
id="serviceRate"
variant="outlined"
placeholder="Enter Service Rate"
value={formik.values.serviceRate}
onChange={formik.handleChange}
size="small"
style={{
width: FORM_PART_VARS.INPUT_BOX_WIDTH,
}}
/>
</Grid>
</Grid>
</div>
<div
style={{
marginLeft: "4%",
marginTop: "4%",
}}
>
<LabelStyling>Select Measurement(s)</LabelStyling>
<FormGroup row>
<FormControlLabel control={<CheckBox checked={nos} onChange={handleNos} name="Nos" id="1"/>} label="Nos" />
<FormControlLabel control={<CheckBox checked={length} onChange={handleLength} name="Length" id="2"/>} label="Length" style={{marginLeft: "15px"}}/>
<FormControlLabel control={<CheckBox checked={breadth} onChange={handleBreadth} name="Breadth" id="3"/>} label="Breadth" style={{marginLeft: "15px"}}/>
<FormControlLabel control={<CheckBox checked={height} onChange={handleHeight} name="Height" id="4"/>} label="Height" style={{marginLeft: "15px"}}/>
</FormGroup>
</div>
<div
style={{
marginLeft: "4%",
marginTop: "4%",
}}
>
<LabelStyling>Select Job Type</LabelStyling>
<FormGroup row>
<FormControlLabel control={<CheckBox name="jobType" value="Residential"/>} label="Residential"/>
<FormControlLabel control={<CheckBox name="jobType" value="Commercial"/>} label="Commercial"/>
<FormControlLabel control={<CheckBox name="jobType" value="Infrastructure"/>} label="Infrastructure"/>
</FormGroup>
</div>
</form>
</>
);
When using Formik , it is not needed to maintain additional state to capture the form field values Formik will take care of that .
In this case , since we need to programmatically change the values of other inputs based on a change in one input we can make use of the setFieldValue prop provided by Formik .
Working Sandbox
To combine multiple states and multiple handlers, try something like this:
const [state, setState] = useState({
nos: false,
length: false,
breadth: false,
height: false
});
const handleCheckBox = useCallback((checkbox) => () => setState(state => {
switch (checkbox) {
case 'nos': return {
...state,
nos: !state.nos,
};
case 'length': return {
...state,
nos: !state.nos,
length: !state.length,
};
case 'breadth': return {
...state,
nos: !state.nos,
length: !state.length,
breadth: !state.breadth,
};
case 'height': return {
...state,
nos: !state.nos,
length: !state.length,
breadth: !state.breadth,
height: !state.height,
};
default: {
console.warn('unknown checkbox', checkbox);
return state;
}
}
}), []);
<FormGroup row>
<FormControlLabel control={<CheckBox checked={state.nos} onChange={handleCheckBox('nos')} name={'Nos'} id={'1'}/>} label={'Nos'}/>
<FormControlLabel control={<CheckBox checked={state.length} onChange={handleCheckBox('length')} name={'Length'} id={'2'}/>} label={'Length'} style={{marginLeft: '15px'}}/>
<FormControlLabel control={<CheckBox checked={state.breadth} onChange={handleCheckBox('breadth')} name={'Breadth'} id={'3'}/>} label={'Breadth'} style={{marginLeft: '15px'}}/>
<FormControlLabel control={<CheckBox checked={state.height} onChange={handleCheckBox('height')} name={'Height'} id={'4'}/>} label={'Height'} style={{marginLeft: '15px'}}/>
</FormGroup>

Formik FieldArray input value for nested form input

I have Formik FieldArray integration in my React Web app as below, but I am not getting values of input field when I enter value in textfield, handleChange event is not working I think. How can I get input values in below case.
From WrapperForm also I am calling different sub form or children. I am not sure how to pass props to children.
return (
<div className={classes.container}>
<Formik
initialValues={{
profile: [
{
id: Math.random(),
firstName: "Test",
lastName: "",
email: ""
}
]
}}
validationSchema={validationSchema}
onSubmit={values => {
console.log("onSubmit", JSON.stringify(values, null, 2));
}}
>
{({ values, touched, errors, handleChange, handleBlur, isValid }) => (
<Form noValidate autoComplete="off">
<FieldArray name="profile">
{({ push, remove }) => (
<div>
{values.profile.map((p, index) => {
return (
<div key={p.id}>
<Grid container spacing={3} >
<Grid item xs={12} sm={6}>
<WrapperForm index = {index} remove={remove} touched={touched} errors={errors} handleChangeOnText={handleChange} handleBlur={handleBlur} />
</Grid>
</Grid>
</div>
);
})}
<Button
className={classes.button}
variant="contained"
color="primary"
startIcon={<AddCircleIcon />}
onClick={() =>
push({ id: Math.random(), firstName: "", lastName: "" })
}
>
Add More
</Button>
</div>
)}
</FieldArray>
<Divider style={{ marginTop: 20, marginBottom: 20 }} />
<Button
className={classes.button}
type="submit"
color="primary"
variant="contained"
// disabled={!isValid || values.people.length === 0}
>
submit
</Button>
<Divider style={{ marginTop: 20, marginBottom: 20 }} />
{debug && (
<>
<pre style={{ textAlign: "left" }}>
<strong>Values</strong>
<br />
{JSON.stringify(values, null, 2)}
</pre>
<pre style={{ textAlign: "left" }}>
<strong>Errors</strong>
<br />
{JSON.stringify(errors, null, 2)}
</pre>
</>
)}
</Form>
)}
</Formik>
WrapperForm.js
export default function HorizontalLinearStepper({index, remove, touched, errors, handleChangeOnText, handleBlur}) {
....
....
function getStepContent(step, index, touched, errors, handleChangeOnText, handleBlur) {
switch (step) {
case 0:
return <Profile index={index} touched={touched} errors={errors} handleChangeOnText=. {handleChangeOnText} handleBlur={handleBlur} />;
case 1:
return <Offer index={index} touched={touched} errors={errors} handleChangeOnText=. {handleChangeOnText} handleBlur={handleBlur} />;
case 2:
return 'This is the bit I really care about!';
default:
return 'Unknown step';
}
}
return (
<div className={classes.layout}>
<Paper variant="outlined" className={classes.paper}>
<Grid container spacing={3}>
<Grid item xs={12} sm={6}>
<TextField
required
id="email"
//name={`${member}.email`}
label="Email"
fullWidth
autoComplete="email"
/>
</Grid>
<Grid item xs={12} sm={4}>
<InputLabel htmlFor="brand-native-simple">Brand</InputLabel>
<Select
native
value={state.brand}
onChange={handleChange}
inputProps={{
name: 'brand',
id: 'brand-native-simple',
}}
>
<option aria-label="None" value="" />
<option value={'gp'}>GAP</option>
<option value={'br'}>BANANA REP</option>
<option value={'on'}>OLDNAVY</option>
</Select>
</Grid>
</Grid>
<Stepper activeStep={activeStep} className={classes.stepper} >
{steps.map((label, index) => {
const stepProps = {};
const labelProps = {};
if (isStepOptional(index)) {
labelProps.optional = <Typography variant="caption">Optional</Typography>;
}
if (isStepSkipped(index)) {
stepProps.completed = false;
}
return (
<Step key={label} {...stepProps}>
<StepLabel {...labelProps}>{label}</StepLabel>
</Step>
);
})}
</Stepper>
<div>
{activeStep === steps.length ? (
<div>
<Typography className={classes.instructions}>
All steps completed - you&apos;re finished
</Typography>
<Button onClick={handleReset} className={classes.button}>
Reset
</Button>
</div>
) : (
<div>
{getStepContent(activeStep, index, touched, errors, handleChangeOnText, handleBlur)}
<div>
<Button disabled={activeStep === 0} onClick={handleBack} className={classes.button}>
Back
</Button>
{isStepOptional(activeStep) && (
<Button
variant="contained"
color="primary"
onClick={handleSkip}
className={classes.button}
>
Skip
</Button>
)}
<Button
variant="contained"
color="primary"
onClick={handleNext}
className={classes.button}
>
{activeStep === steps.length - 1 ? 'Finish' : 'Next'}
</Button>
<Button
variant="contained"
color="secondary"
className={classes.button}
startIcon={<DeleteIcon />}
onClick={() => remove(index)}
>
Remove
</Button>
</div>
</div>
)}
I see some problems with your code here, first thing is you have to pass formik values as props to WrapperForm,
<WrapperForm values={values} {...otherPropsYouArePassing} />
Next you need to iterate over these values in the WrapperForm:
<div>
{
// You are getting these values from props in WrapperForm
values.profile &&
values.profile.length > 0 &&
values.profile.map((x, idx) => {
// Return you JSX here
return (...);
})
}
</div>
And lastly you need to name your inputs right like these:
// I'm assuming your data structure to be like this
/*
{
profile: [{ email: '', ... }, ...]
}
*/
<TextField
required
id="email"
name={`profile[${idx}].email`} // We're getting idx from the map above
label="Email"
fullWidth
autoComplete="email"
/>

Resources