remix-validated-form 4.5.6 → 4.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remix-validated-form",
3
- "version": "4.5.6",
3
+ "version": "4.5.7",
4
4
  "description": "Form component and utils for easy form validation in remix",
5
5
  "browser": "./dist/remix-validated-form.cjs.js",
6
6
  "main": "./dist/remix-validated-form.umd.js",
@@ -1,4 +1,9 @@
1
- import { Form as RemixForm, useFetcher, useSubmit } from "@remix-run/react";
1
+ import {
2
+ Form as RemixForm,
3
+ FormMethod,
4
+ useFetcher,
5
+ useSubmit,
6
+ } from "@remix-run/react";
2
7
  import uniq from "lodash/uniq";
3
8
  import React, {
4
9
  ComponentProps,
@@ -303,7 +308,13 @@ export function ValidatedForm<DataType>({
303
308
  nativeEvent: HTMLSubmitEvent["nativeEvent"]
304
309
  ) => {
305
310
  startSubmit();
306
- const result = await validator.validate(getDataFromForm(e.currentTarget));
311
+ const submitter = nativeEvent.submitter as HTMLFormSubmitter | null;
312
+ const formDataToValidate = getDataFromForm(e.currentTarget);
313
+ if (submitter?.name) {
314
+ formDataToValidate.append(submitter.name, submitter.value);
315
+ }
316
+
317
+ const result = await validator.validate(formDataToValidate);
307
318
  if (result.error) {
308
319
  setFieldErrors(result.error.fieldErrors);
309
320
  endSubmit();
@@ -315,6 +326,7 @@ export function ValidatedForm<DataType>({
315
326
  );
316
327
  }
317
328
  } else {
329
+ setFieldErrors({});
318
330
  const eventProxy = formEventProxy(e);
319
331
  await onSubmit?.(result.data, eventProxy);
320
332
  if (eventProxy.defaultPrevented) {
@@ -322,15 +334,17 @@ export function ValidatedForm<DataType>({
322
334
  return;
323
335
  }
324
336
 
325
- const submitter = nativeEvent.submitter as HTMLFormSubmitter | null;
326
-
327
337
  // We deviate from the remix code here a bit because of our async submit.
328
338
  // In remix's `FormImpl`, they use `event.currentTarget` to get the form,
329
339
  // but we already have the form in `formRef.current` so we can just use that.
330
340
  // If we use `event.currentTarget` here, it will break because `currentTarget`
331
341
  // will have changed since the start of the submission.
332
342
  if (fetcher) fetcher.submit(submitter || e.currentTarget);
333
- else submit(submitter || target, { replace });
343
+ else
344
+ submit(submitter || target, {
345
+ replace,
346
+ method: (submitter?.formMethod as FormMethod) || method,
347
+ });
334
348
  }
335
349
  };
336
350
 
@@ -1,3 +1,4 @@
1
+ import omit from "lodash/omit";
1
2
  import { CreateValidatorArg, GenericObject, Validator } from "..";
2
3
  import { FORM_ID_FIELD } from "../internal/constants";
3
4
  import { objectFromPathEntries } from "../internal/flatten";
@@ -10,6 +11,9 @@ const preprocessFormData = (data: GenericObject | FormData): GenericObject => {
10
11
  return objectFromPathEntries(Object.entries(data));
11
12
  };
12
13
 
14
+ const omitInternalFields = (data: GenericObject): GenericObject =>
15
+ omit(data, FORM_ID_FIELD);
16
+
13
17
  /**
14
18
  * Used to create a validator for a form.
15
19
  * It provides built-in handling for unflattening nested objects and
@@ -21,7 +25,7 @@ export function createValidator<T>(
21
25
  return {
22
26
  validate: async (value) => {
23
27
  const data = preprocessFormData(value);
24
- const result = await validator.validate(data);
28
+ const result = await validator.validate(omitInternalFields(data));
25
29
 
26
30
  if (result.error) {
27
31
  return {
@@ -1,11 +1,13 @@
1
1
  import { anyString, TestFormData } from "@remix-validated-form/test-utils";
2
2
  import { withYup } from "@remix-validated-form/with-yup/src";
3
3
  import { withZod } from "@remix-validated-form/with-zod";
4
+ import omit from "lodash/omit";
4
5
  import { Validator } from "remix-validated-form/src";
5
6
  import { objectFromPathEntries } from "remix-validated-form/src/internal/flatten";
6
7
  import { describe, it, expect } from "vitest";
7
8
  import * as yup from "yup";
8
9
  import { z } from "zod";
10
+ import { FORM_ID_FIELD } from "../internal/constants";
9
11
 
10
12
  // If adding an adapter, write a validator that validates this shape
11
13
  type Person = {
@@ -101,6 +103,30 @@ describe("Validation", () => {
101
103
  });
102
104
  });
103
105
 
106
+ it("should omit internal fields", async () => {
107
+ const person: Person = {
108
+ firstName: "John",
109
+ lastName: "Doe",
110
+ age: 30,
111
+ address: {
112
+ streetAddress: "123 Main St",
113
+ city: "Anytown",
114
+ country: "USA",
115
+ },
116
+ pets: [{ animal: "dog", name: "Fido" }],
117
+
118
+ // @ts-expect-error
119
+ // internal filed technically not part of person type
120
+ [FORM_ID_FIELD]: "something",
121
+ };
122
+ expect(await validator.validate(person)).toEqual({
123
+ data: omit(person, FORM_ID_FIELD),
124
+ error: undefined,
125
+ submittedData: person,
126
+ formId: "something",
127
+ });
128
+ });
129
+
104
130
  it("should return field errors when invalid", async () => {
105
131
  const obj = { age: "hi!", pets: [{ animal: "dog" }] };
106
132
  expect(await validator.validate(obj)).toEqual({