Skip to content

Commit c505247

Browse files
committed
Allow to revert remove in mui field array
1 parent cc38ee0 commit c505247

File tree

3 files changed

+634
-35
lines changed

3 files changed

+634
-35
lines changed

packages/mui-component-mapper/demo/demo-schemas/field-array-schema.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const arraySchemaDDF = {
77
fieldKey: 'field_array',
88
label: 'Nice people',
99
description: 'This allow you to add nice people to the list dynamically',
10-
itemDefault: { name: 'enter a name', lastName: 'enter a last name' },
10+
defaultItem: { name: 'enter a name', lastName: 'enter a last name' },
1111
fields: [
1212
{
1313
component: 'text-field',

packages/mui-component-mapper/src/files/field-array.js

Lines changed: 99 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useReducer } from 'react';
22
import PropTypes from 'prop-types';
33
import { useFormApi, FieldArray } from '@data-driven-forms/react-form-renderer';
44

@@ -8,6 +8,9 @@ import Typography from '@material-ui/core/Typography';
88
import FormControl from '@material-ui/core/FormControl';
99
import FormHelperText from '@material-ui/core/FormHelperText';
1010
import { makeStyles } from '@material-ui/core/styles';
11+
import RedoIcon from '@material-ui/icons/Redo';
12+
import UndoIcon from '@material-ui/icons/Undo';
13+
import IconButton from '@material-ui/core/IconButton';
1114

1215
import { useFieldApi } from '@data-driven-forms/react-form-renderer';
1316

@@ -77,6 +80,38 @@ const defaultButtonLabels = {
7780
remove: 'REMOVE'
7881
};
7982

83+
const initialState = {
84+
index: 0,
85+
history: []
86+
};
87+
88+
export const reducer = (state, { type, action }) => {
89+
switch (type) {
90+
case 'redo':
91+
return {
92+
...state,
93+
index: state.index + 1
94+
};
95+
case 'action':
96+
return {
97+
index: state.index + 1,
98+
history: [...state.history.slice(0, state.index), action]
99+
};
100+
case 'undo':
101+
return {
102+
...state,
103+
index: state.index - 1
104+
};
105+
case 'resetHistory':
106+
return {
107+
...state,
108+
history: state.history.slice(0, state.index)
109+
};
110+
default:
111+
return state;
112+
}
113+
};
114+
80115
const DynamicArray = ({ ...props }) => {
81116
const {
82117
arrayValidator,
@@ -93,6 +128,7 @@ const DynamicArray = ({ ...props }) => {
93128
buttonLabels,
94129
...rest
95130
} = useFieldApi(props);
131+
const [state, dispatch] = useReducer(reducer, initialState);
96132

97133
const combinedButtonLabels = {
98134
...defaultButtonLabels,
@@ -108,51 +144,80 @@ const DynamicArray = ({ ...props }) => {
108144
<FormFieldGrid {...FormFieldGridProps} className={clsx(classes.fieldArrayGroup, FormFieldGridProps.classname)}>
109145
<FormControl component="fieldset" error={isError} {...FormControlProps} className={clsx(classes.formControl, FormControlProps.className)}>
110146
<FieldArray key={rest.input.name} name={rest.input.name} validate={arrayValidator}>
111-
{({ fields: { map, value = [], push, remove } }) => (
112-
<Grid container spacing={3}>
113-
{label && (
147+
{({ fields: { map, value = [], push, remove } }) => {
148+
const pushWrapper = () => {
149+
dispatch({ type: 'resetHistory' });
150+
push(defaultItem);
151+
};
152+
153+
const removeWrapper = (index) => {
154+
dispatch({ type: 'action', action: { action: 'remove', value: value[index] } });
155+
remove(index);
156+
};
157+
158+
const undo = () => {
159+
push(state.history[state.index - 1].value);
160+
161+
dispatch({ type: 'undo' });
162+
};
163+
164+
const redo = () => {
165+
remove(value.length - 1);
166+
167+
dispatch({ type: 'redo' });
168+
};
169+
170+
return (
171+
<Grid container spacing={3}>
114172
<Grid item xs={12} className={classes.header}>
115-
<Typography variant="h6" className={classes.label}>
116-
{label}
117-
</Typography>
118-
<Button color="primary" onClick={() => push(defaultItem)} disabled={value.length >= maxItems}>
173+
{label && (
174+
<Typography variant="h6" className={classes.label}>
175+
{label}
176+
</Typography>
177+
)}
178+
<IconButton color="primary" aria-label="undo" component="span" disabled={state.index === 0} onClick={undo}>
179+
<UndoIcon />
180+
</IconButton>
181+
<IconButton color="primary" aria-label="redo" component="span" disabled={state.index === state.history.length} onClick={redo}>
182+
<RedoIcon />
183+
</IconButton>
184+
<Button color="primary" onClick={pushWrapper} disabled={value.length >= maxItems}>
119185
{combinedButtonLabels.add}
120186
</Button>
121187
</Grid>
122-
)}
123-
{description && (
124-
<Grid item xs={12}>
125-
<Typography variant="subtitle1">{description}</Typography>
126-
</Grid>
127-
)}
128-
{value.length <= 0 && (
188+
{description && (
189+
<Grid item xs={12}>
190+
<Typography variant="subtitle1">{description}</Typography>
191+
</Grid>
192+
)}
129193
<Grid item xs={12}>
130-
<Typography variant="body1" gutterBottom className={classes.centerText}>
131-
{noItemsMessage}
132-
</Typography>
194+
{value.length <= 0 ? (
195+
<Typography variant="body1" gutterBottom className={classes.centerText}>
196+
{noItemsMessage}
197+
</Typography>
198+
) : (
199+
map((name, index) => (
200+
<ArrayItem
201+
key={`${name}-${index}`}
202+
fields={formFields}
203+
name={name}
204+
fieldIndex={index}
205+
remove={removeWrapper}
206+
length={value.length}
207+
minItems={minItems}
208+
removeLabel={combinedButtonLabels.remove}
209+
/>
210+
))
211+
)}
133212
</Grid>
134-
)}
135-
<Grid item xs={12}>
136-
{map((name, index) => (
137-
<ArrayItem
138-
key={`${name}-${index}`}
139-
fields={formFields}
140-
name={name}
141-
fieldIndex={index}
142-
remove={remove}
143-
length={value.length}
144-
minItems={minItems}
145-
removeLabel={combinedButtonLabels.remove}
146-
/>
147-
))}
148213
{isError && (
149214
<Grid item xs={12}>
150215
<FormHelperText>{error}</FormHelperText>
151216
</Grid>
152217
)}
153218
</Grid>
154-
</Grid>
155-
)}
219+
);
220+
}}
156221
</FieldArray>
157222
</FormControl>
158223
</FormFieldGrid>

0 commit comments

Comments
 (0)