You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: TODO.md
+1-2
Original file line number
Diff line number
Diff line change
@@ -2,8 +2,7 @@
2
2
3
3
## Priority
4
4
5
-
-[ ] Add docs on how to reconcile error messages between server and client.
6
-
-[ ] Consider doing this AFTER releasing `0.9.0` if you need to.
5
+
-[ ] Update `SuperTokens + Remix` and `SuperTokens + SvelteKit` examples with the stateful `errors` object approach (if it would be easier to understand/read).
Copy file name to clipboardexpand all lines: docs/form-validity-observer/guides.md
+201-2
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,7 @@ Here you'll find helpful tips on how to use the `FormValidityObserver` effective
6
6
-[Keeping Track of Visited/Dirty Fields](#keeping-track-of-visiteddirty-fields)
7
7
-[Getting the Most out of the `defaultErrors` option](#getting-the-most-out-of-the-defaulterrors-option)
8
8
-[Managing Form Errors with State](#managing-form-errors-with-state)
9
+
-[Reconciling Server Errors with Client Errors in Forms](#reconciling-server-errors-with-client-errors-in-forms)
9
10
-[Keeping Track of Form Data](#keeping-track-of-form-data)
10
11
-[Recommendations for Conditionally Rendered Fields](#recommendations-for-conditionally-rendered-fields)
11
12
-[Recommendations for Styling Form Fields and Their Error Messages](#recommendations-for-styling-form-fields-and-their-error-messages)
@@ -14,8 +15,7 @@ Here you'll find helpful tips on how to use the `FormValidityObserver` effective
14
15
<!--
15
16
TODO: Some `Guides` that could be helpful:
16
17
17
-
1) Reconciling error messages sent by the server on the client side.
18
-
2) MAYBE something on how to work with accessible error messages? (Should we also mention `aria-errormessage` vs. `aria-describedby` too? As well as the lack of support for `aria-errormessage`? Or does that belong somewhere else in the docs?)
18
+
1) MAYBE something on how to work with accessible error messages? (Should we also mention `aria-errormessage` vs. `aria-describedby` too? As well as the lack of support for `aria-errormessage`? Or does that belong somewhere else in the docs?)
19
19
-->
20
20
21
21
## Enabling Accessible Error Messages during Form Submissions
@@ -357,6 +357,205 @@ Notice that we also supplied the [`renderByDefault: true`](./README.md#form-vali
357
357
358
358
You can find more detailed examples of using stateful error objects on [StackBlitz](https://stackblitz.com/@ITenthusiasm/collections/form-observer-examples).
359
359
360
+
## Reconciling Server Errors with Client Errors in Forms
361
+
362
+
It's common for server-rendered applications to have both server-side validation logic and client-side validation logic for forms. Usually, the validation logic is the same between the client and the server. But in some situations, you may have validation logic that you _only_ want to run on the server. For example, the logic for verifying that a user + password combination is correct should only be run on the server. In cases like these, you'll need a way to combine/reconcile your server-side errors with your client-side errors so that your users will know what they need to fix.
363
+
364
+
There are multiple ways to go about this. We'll be showing 2 approaches that use [`Remix`](https://remix.run/) and [`Zod`](https://zod.dev/), and we'll be managing our error messages [with state](#managing-form-errors-with-state) (instead of manipulating the DOM directly). The examples that you see below should be easily transferrable to other frameworks (such as `SvelteKit`) and other validators (such as `yup`, or even your own server logic). If you're interested in manipulating the DOM directly (instead of using state), you're free to do that as well.
365
+
366
+
### 1) Using `Zod` for Server-side Validation and the Browser for Client-side Validation
367
+
368
+
In this first approach, we _will not_ use `Zod` on the frontend. Oftentimes, the browser is sufficient for running client-side validation. One of the biggest benefits of using the browser's validation logic is that it works even when your users have [no access to JavaScript](https://www.kryogenix.org/code/browser/everyonehasjs.html). In such cases, the browser will be able to tell your users how to correct their forms _without_ making roundtrips to your server. Additionally, by keeping `Zod` out of your client bundle, you save a significant amount of space (roughly 13.8 kb).
Although this approach does allow us to keep our client bundle smaller, you'll notice that it also results in us having to duplicate our error messages on the server and the client. One way around this problem is to create an `errorMessages` object that both the server and the client can share, like so:
463
+
464
+
```ts
465
+
consterrorMessages= {
466
+
username: { required:"Username is required", minlength:"Minimum length is 5 characters" },
467
+
email: { required:"Email is required", format:"Email is not valid" },
468
+
} as const;
469
+
```
470
+
471
+
Then, our frontend could use this object to define its error messages:
This approach allows us to reduce code duplication between the client and the server with ease _while also keeping our client bundle smaller_. So it's worth considering!
496
+
497
+
### 2) Using `Zod` Exclusively for Both Server _and_ Client-side Validation
498
+
499
+
If you're really bothered by the idea of having to create an `errorMessages` object that both the server and the client can share, then another alternative is to just use Zod on _both_ the server _and_ the client. Be warned: _This will noticeably increase your client's JavaScript bundle size_, and it might have more impacts on performance/maintainability than you expect (especially for complex forms). Additionally, you will no longer be able to take advantage of the browser's validation logic. This means that when users of your application lack access to JavaScript, they will keep having to make roundtrips to your server to know how to fix their forms (instead of having the browser tell them immediately without making any network requests).
500
+
501
+
Nonetheless, this approach removes the need for an `errorMessages` object. So, if that is your preferred approach, please see below. (We will only show the code for the frontend here because that is the only code that needs to change.)
In the end, it's up to you to decide how you want to handle these trade-offs. There is no "perfect" solution.
556
+
557
+
There is potential for a third option that would allow you to pull benefits from both of the approaches shown above. However, that third option would also pull _drawbacks_ from both of those approaches. (We can never avoid the difficulties of making real trade-offs.) If you're interested in that third option being supported, feel free to comment on [this issue](https://github.com/enthusiastic-js/form-observer/issues/7).
558
+
360
559
## Keeping Track of Form Data
361
560
362
561
Many form libraries offer stateful solutions for managing the data in your forms as JSON. But there are a few disadvantages to this approach:
0 commit comments