()
+
+ return {JSON.stringify(watch("items"))}
+}
+
+function TestComponent(): React.JSX.Element {
+ const methods = useForm({
+ defaultValues: {
+ items: [
+ {
+ value: "BABYBIBXA19D9D000000XXXX",
+ quantity: 2,
+ },
+ {
+ value: "BASEBHAT000000FFFFFFXXXX",
+ quantity: 3,
+ },
+ ],
+ },
+ })
+
+ return (
+
+
+
+
+
+ )
+}
+
+describe("HookedInputCheckboxGroup", () => {
+ test("preserves extra item fields after nested setValue and toggle", () => {
+ const { getAllByTestId, getByRole, getByTestId } = render()
+
+ fireEvent.click(getByRole("button", { name: "Set reason" }))
+ expect(getByTestId("values").textContent).toContain('"reason":"Damaged"')
+
+ const [, secondItem] = getAllByTestId("InputCheckboxGroupItem")
+ assertToBeDefined(secondItem)
+
+ fireEvent.click(secondItem)
+
+ const values = JSON.parse(getByTestId("values").textContent ?? "null")
+ expect(values).toEqual([
+ {
+ value: "BABYBIBXA19D9D000000XXXX",
+ quantity: 2,
+ reason: "Damaged",
+ },
+ ])
+ })
+})
diff --git a/packages/app-elements/src/ui/forms/InputCheckboxGroup/HookedInputCheckboxGroup.tsx b/packages/app-elements/src/ui/forms/InputCheckboxGroup/HookedInputCheckboxGroup.tsx
index dd148db8b..bc71affa2 100644
--- a/packages/app-elements/src/ui/forms/InputCheckboxGroup/HookedInputCheckboxGroup.tsx
+++ b/packages/app-elements/src/ui/forms/InputCheckboxGroup/HookedInputCheckboxGroup.tsx
@@ -20,7 +20,7 @@ export interface HookedInputCheckboxGroupProps
export const HookedInputCheckboxGroup: React.FC<
HookedInputCheckboxGroupProps
> = ({ name, ...props }) => {
- const { control } = useFormContext()
+ const { control, getValues } = useFormContext()
const feedback = useValidationFeedback(name)
return (
@@ -31,9 +31,29 @@ export const HookedInputCheckboxGroup: React.FC<
{
- field.onChange(values)
+ // Preserve any extra fields (e.g. `reason`) that the consumer
+ // stored on existing items via setValue. We need the latest form
+ // snapshot here because field.value can lag behind nested updates.
+ const currentValue = getValues(name)
+ const current: Array<{ value: string }> = Array.isArray(
+ currentValue,
+ )
+ ? currentValue.filter(
+ (v): v is { value: string } =>
+ typeof v === "object" &&
+ v !== null &&
+ "value" in v &&
+ typeof (v as { value: unknown }).value === "string",
+ )
+ : []
+ field.onChange(
+ values.map((item) => {
+ const existing = current.find((v) => v.value === item.value)
+ return existing != null ? { ...existing, ...item } : item
+ }),
+ )
}}
/>
)}