ciscoheat / sveltekit-superforms

Making SvelteKit forms a pleasure to use!
https://superforms.rocks
MIT License
2.23k stars 66 forks source link

Form starts as tainted with Zod enums and select elements #73

Closed abastardi closed 1 year ago

abastardi commented 1 year ago

I have an address form with the state property of the Zod schema defined like:

    state: z.nativeEnum(State)

In the form, the state field is a select element with the first option defined as:

            <option value="">Select</option>

The problem is that superValidate generates undefined as the value of $form.state, but when bound to the select element, that immediately gets changed to the empty string, which marks the form as tainted. This means even without touching the form, if the user attempts to navigate away, they will see the taintedMessage alert.

To avoid this problem, it would be helpful to be able to specify the default value for enums as being the empty string rather than undefined (possibly via a configuration option). For example, the following schema works as expected:

    state: z.nativeEnum(State).or(z.literal('')).default(''),

Of course, it's not ideal to have to specify the schema that way, as it is not obvious why it is written that way, and technically it would allow an empty string to be submitted even though that value should not be allowed.

Would adding an option to handle this case be possible, or is there a better solution?

ciscoheat commented 1 year ago

That's a good catch. As a workaround until I've examined this better, does this work?

z.nativeEnum(State).default('' as State)
abastardi commented 1 year ago

Nice idea -- yes, that works. Thanks.

ciscoheat commented 1 year ago

Great! There's a note about this (ab)use of the type system here: https://superforms.vercel.app/default-values#changing-a-default-value

ciscoheat commented 1 year ago

Closing this, I think the workaround is the only thing to do if the general type safety of the library is to be kept.

abastardi commented 1 year ago

Note, it might be worth mentioning this issue and the workaround in the Tainted form check section of the docs, as it may not be obvious to users why they are getting the taintedMessage alert unexpectedly (there is no clear indication that the <select> is what is tainted nor why it has become tainted, so it won't be obvious that this workaround is even needed).

ciscoheat commented 1 year ago

Yes, will add that to the docs.