Skip to content

Commit

Permalink
feat(core): addItem and removeItem methods for array field handle (#30)
Browse files Browse the repository at this point in the history
Co-authored-by: Mikołaj Klaman <mklaman@virtuslab.com>
  • Loading branch information
mixvar and Mikołaj Klaman authored Nov 4, 2020
1 parent 83ed049 commit a9bb040
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 3 deletions.
37 changes: 37 additions & 0 deletions src/core/hooks/use-formts/use-formts.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,43 @@ describe("useFormts", () => {
}
});

it("allows for adding and removing array field items", () => {
const hook = renderHook(() => useFormts({ Schema }));

{
const [fields] = hook.result.current;
expect(fields.theArray.isTouched).toBe(false);
expect(fields.theArray.value).toEqual([]);
}

act(() => {
const [fields] = hook.result.current;
fields.theArray.addItem("foo");
});

act(() => {
const [fields] = hook.result.current;
fields.theArray.addItem("bar");
});

{
const [fields] = hook.result.current;
expect(fields.theArray.isTouched).toBe(true);
expect(fields.theArray.value).toEqual(["foo", "bar"]);
}

act(() => {
const [fields] = hook.result.current;
fields.theArray.removeItem(0);
});

{
const [fields] = hook.result.current;
expect(fields.theArray.isTouched).toBe(true);
expect(fields.theArray.value).toEqual(["bar"]);
}
});

it("allows for setting errors using corresponding field handles and keeps track of isValid state", () => {
const hook = renderHook(() => useFormts({ Schema }));

Expand Down
20 changes: 20 additions & 0 deletions src/core/hooks/use-formts/use-formts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,26 @@ export const useFormts = <Values extends object, Err>(
setFieldErrors({ field: descriptor, error });
},

addItem: item => {
if (isArrayDescriptor(descriptor)) {
const array = getField(descriptor) as unknown[];
const updatedArray = [...array, item];
return setField(descriptor, updatedArray);
}

return undefined;
},

removeItem: index => {
if (isArrayDescriptor(descriptor)) {
const array = getField(descriptor) as unknown[];
const updatedArray = array.filter((_, i) => i !== index);
return setField(descriptor, updatedArray);
}

return undefined;
},

validate: () => {
return validateField(descriptor);
},
Expand Down
8 changes: 5 additions & 3 deletions src/core/types/field-handle.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IdentityDict, IsUnion } from "../../utils";
import { ArrayElement, IdentityDict, IsUnion } from "../../utils";

import { FieldDescriptor } from "./field-descriptor";

Expand All @@ -17,6 +17,8 @@ export type _FieldHandleApprox<T, Err> = BaseFieldHandle<T, Err> & {
| Array<_FieldHandleApprox<unknown, Err>>
| Record<string, _FieldHandleApprox<unknown, Err>>;
options?: Record<string, string>;
addItem?: (item: ArrayElement<T>) => void;
removeItem?: (i: number) => void;
};

export const toApproxFieldHandle = <T, Err>(it: FieldHandle<T, Err>) =>
Expand Down Expand Up @@ -81,14 +83,14 @@ type ArrayFieldHandle<T, Err> = T extends Array<infer E>
* Will run field validation with `change` trigger.
* Will set `isTouched` to `true`.
*/
// pushItem: (item: E) => void;
addItem: (item: E) => void;

/**
* Will set the field value its copy with the item at index `i` removed.
* Will run field validation with `change` trigger.
* Will set `isTouched` to `true`.
*/
// removeItem: (i: number) => void;
removeItem: (i: number) => void;

/**
* Array of FieldHandles for each item stored in field value
Expand Down

0 comments on commit a9bb040

Please sign in to comment.