Skip to content

Commit 1be1128

Browse files
authored
feat: remove in Form.list support array (#165)
* feat: remove in Form.LIst support array * feat: remove in Form.list support array * mod: add test case * update logical * add more test case * update typo * fix: test case * update test case * add test case
1 parent 195affa commit 1be1128

File tree

2 files changed

+130
-14
lines changed

2 files changed

+130
-14
lines changed

src/List.tsx

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ interface ListField {
1313

1414
interface ListOperations {
1515
add: (defaultValue?: StoreValue) => void;
16-
remove: (index: number) => void;
16+
remove: (index: number | number[]) => void;
1717
move: (from: number, to: number) => void;
1818
}
1919

@@ -67,25 +67,17 @@ const List: React.FunctionComponent<ListProps> = ({ name, children }) => {
6767
const newValue = getNewValue();
6868
onChange([...newValue, defaultValue]);
6969
},
70-
remove: (index: number) => {
70+
remove: (index: number | number[]) => {
7171
const newValue = getNewValue();
72+
const indexSet = new Set(Array.isArray(index) ? index : [index]);
7273

73-
// Do not handle out of range
74-
if (index < 0 || index >= newValue.length) {
74+
if (indexSet.size <= 0) {
7575
return;
7676
}
77-
78-
// Update key mapping
79-
const newKeys = keyManager.keys.map((key, id) => {
80-
if (id < index) {
81-
return key;
82-
}
83-
return keyManager.keys[id + 1];
84-
});
85-
keyManager.keys = newKeys.slice(0, -1);
77+
keyManager.keys = keyManager.keys.filter((_, keysIndex) => !indexSet.has(keysIndex));
8678

8779
// Trigger store change
88-
onChange(newValue.filter((_, id) => id !== index));
80+
onChange(newValue.filter((_, valueIndex) => !indexSet.has(valueIndex)));
8981
},
9082
move(from: number, to: number) {
9183
if (from === to) {

tests/list.test.js

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,89 @@ describe('Form.List', () => {
217217
matchKey(1, '2');
218218
});
219219

220+
it('remove when the param is Array', () => {
221+
let operation;
222+
const [wrapper, getList] = generateForm((fields, opt) => {
223+
operation = opt;
224+
return (
225+
<div>
226+
{fields.map(field => (
227+
<Field {...field}>
228+
<Input />
229+
</Field>
230+
))}
231+
</div>
232+
);
233+
});
234+
235+
function matchKey(index, key) {
236+
expect(
237+
getList()
238+
.find(Field)
239+
.at(index)
240+
.key(),
241+
).toEqual(key);
242+
}
243+
244+
act(() => {
245+
operation.add();
246+
});
247+
248+
act(() => {
249+
operation.add();
250+
});
251+
252+
wrapper.update();
253+
expect(getList().find(Field).length).toEqual(2);
254+
255+
// remove empty array
256+
act(() => {
257+
operation.remove([]);
258+
});
259+
260+
wrapper.update();
261+
262+
matchKey(0, '0');
263+
matchKey(1, '1');
264+
265+
// remove not esist element in array
266+
act(() => {
267+
operation.remove([-1, 99]);
268+
});
269+
wrapper.update();
270+
271+
matchKey(0, '0');
272+
matchKey(1, '1');
273+
274+
act(() => {
275+
operation.remove([0]);
276+
});
277+
278+
wrapper.update();
279+
expect(getList().find(Field).length).toEqual(1);
280+
matchKey(0, '1');
281+
282+
act(() => {
283+
operation.add();
284+
});
285+
286+
act(() => {
287+
operation.add();
288+
});
289+
290+
wrapper.update();
291+
matchKey(0, '1');
292+
matchKey(1, '2');
293+
matchKey(2, '3');
294+
295+
act(() => {
296+
operation.remove([0, 1]);
297+
});
298+
299+
wrapper.update();
300+
matchKey(0, '3');
301+
});
302+
220303
describe('validate', () => {
221304
it('basic', async () => {
222305
const [, getList] = generateForm(
@@ -272,6 +355,47 @@ describe('Form.List', () => {
272355
expect(wrapper.find(Input)).toHaveLength(1);
273356
expect(form.getFieldError(['list', 0])).toEqual(["'list.1' is required"]);
274357
});
358+
359+
it('when param of remove is array', async () => {
360+
const [wrapper, getList] = generateForm(
361+
(fields, { remove }) => (
362+
<div>
363+
{fields.map(field => (
364+
<Field {...field} rules={[{ required: true }, { min: 5 }]}>
365+
<Input />
366+
</Field>
367+
))}
368+
369+
<button
370+
type="button"
371+
onClick={() => {
372+
remove([0, 2]);
373+
}}
374+
/>
375+
</div>
376+
),
377+
{
378+
initialValues: { list: ['', '', ''] },
379+
},
380+
);
381+
382+
expect(wrapper.find(Input)).toHaveLength(3);
383+
await changeValue(getField(getList(), 0), '');
384+
expect(form.getFieldError(['list', 0])).toEqual(["'list.0' is required"]);
385+
386+
await changeValue(getField(getList(), 1), 'test');
387+
expect(form.getFieldError(['list', 1])).toEqual(["'list.1' must be at least 5 characters"]);
388+
389+
await changeValue(getField(getList(), 2), '');
390+
expect(form.getFieldError(['list', 2])).toEqual(["'list.2' is required"]);
391+
392+
wrapper.find('button').simulate('click');
393+
wrapper.update();
394+
395+
expect(wrapper.find(Input)).toHaveLength(1);
396+
expect(form.getFieldError(['list', 0])).toEqual(["'list.1' must be at least 5 characters"]);
397+
expect(wrapper.find('input').props().value).toEqual('test');
398+
});
275399
});
276400

277401
it('warning if children is not function', () => {

0 commit comments

Comments
 (0)