-
-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature]: support expected behavior of novalidate
and formnovalidate
#207
Comments
I'm feeling better about this direction the more I think about it. Thanks for opening up the discussion 👍 A couple thoughts / questions to figure out. What if, instead changing the behavior of We could still fully support What should we do about the It seems bad not to call the submit callback, but we also can't really provide anything better than the raw submit event in that case. Trying to think of ways we can make that work without requiring normal usage to require |
Another thought: Changing the function signature of Just a sketch of an idea: onSubmit={async (event) => {
// identical to the normal event
// but enhanced with more properties
// data is a promise that rejects if `noValidate`
// That way we can keep the strict types
await event.data;
// false when noValidate.
// in case you want to handle both cases
event.validated;
// Since we're adding stuff, this would be convenient.
// Also includes the data from the clicked button, which is normally an extra step
event.formData;
}} So migrating would look like this - onSubmit={(data, event) => {
+ onSubmit={async (event) => {
+ const data = await event.data; It guess it doesn't gain that much over just requiring |
That's a good question. I personally never have encountered a use-case for I do think those are edge-cases though and this isn't possible with the current implementation of
I think dropping I didn't thought about |
Just an idea for onSubmit={async (event) => {
const { errors, data, submittedData } = await event.validate();
// or
const { error, data, submittedData } = await event.validateField('name')
} - type ValidateFieldResult = { error?: string };
+ type ValidateFieldResult<DataFieldType> = { error?: string, data?: DataFieldType }; And I think |
Looking more closely at Just a thought, but maybe leaving the option for devs to use the Food for thoughts: onSubmit={async (event) => {
const { errors, data, submittedData } = await event.validate();
if (errors) return // void/truthy to let remix-validated-form take over, to show the errors etc.
if (data.is_valid_but_in_some_intricate_condition) { // which might include third party data
// do something in my user's space
e.preventDefault() // do not submit,
return // void/truthy to let remix-validated-form do its magic
}
if (data.is_valid_but_in_some_other_intricate_condition) { // which might include third party data
// do something in my user's space
// return false to indicate that remix-validated-form internal validation should be skipped
// no setFieldErrors and no focus first invalid field etc. and no submit should occur
return false
}
}} |
On second thought, I'm not sure about my latest comments, native validation does occur before |
Yeah, I'm definitely leaning this way. We could add
Unfortunately, I don't think the native submit event includes a
Yeah, right now the only disadvantage I can think of is the churn aspect. I want to think on it for a couple more days to see if anything comes to me. |
I completely strayed away on my previous comments on this Coming back to your proposal, after giving this a couple of days of thinking, I wonder in which instance I'd need to have a custom event with I wonder wether validated and parsed/typed I understand your intent of adding those properties to make it easier to handle those different cases but I believe this might induce wrong expectations and inappropriate usages of Thus, I wanted to find a use-case where https://github.com/search?p=1&q=ValidatedForm+onSubmit+remix-validated-form&type=Code That's certainly not exhaustive and full-proof but after going through the 22 results that search returned to me; the only case which seemed to use In this instance, it appears to be for adding the "files" dropped in a However, I do think it should be possible to programmatically check if the form's content has been validated in And with const { result, data } = await validator.validate(new FormData(formRefOrFormEventTarget)) TL;DR – I think |
I think being able to access the validated data in I also think submitting an AJAX request instead of using the Remix / native submit behavior is a perfectly valid case. I totally found an example in those search results of someone doing that when they didn't need to though, so it may be worth documenting that this isn't the primary way to do things. Ultimately, even after a few days, I still think switching to a more native-ish api makes sense. Though I do want to augment the event with custom properties (we already do that for One last thing to bikeshed for me would be, which one of these two should we go with?
|
Something I just thought of. Before we set |
I unfortunately don't have access to this repository, it must be private. But I can guess how such use-case could simply be solved with something akin to: onSubmit={e => {
e.preventDefault()
// assuming consumer should always do it's own validation anyway, data can be send raw
sendMessage({ message: refInput.current.value })
// or still raw
sendMessage(Object.fromEntries(new FormData(e.currentTarget))
// or if for some reason some data parsing is required client-side (consumer should never trust
// client to send valid data but the client might still need to transform data for it to be accepted
// by the consumer)
const { data } = await validator.validate(new FormData(e.currentTarget)) // with async on function
// perhaps the form was submitted with "novalidate" and the data isn't valid
// and can't be parsed as expected
if (!data) return console.log('oups')
sendMessage({ message: data.message })
}
What I was trying to point out in my previous comment is that there's also many examples where
I think leveraging custom validation would be a great approach to make it possible to check a form or input validity at any time, that would leverage native API and makes
This however, I'm not sure. I believe the native UI doesn't provide the kind of UX and controls that devs using this library might be looking for. As an example I use |
Whoops! Yeah, I was wondering why that showed up (I guess that makes sense now).
Getting the correct, validated form data isn't something I think we should push onto users. It's more than simply doing
I definitely agree with this. I think anything we go with from here will be less obvious than providing the data directly as a parameter. On top of having to call onSubmit={async (event) => {
event.preventDefault();
const data = await event.data;
// Do something else
}} I'm open to bikeshedding the exact api. These helpers don't necessarily need to be accessed off the event -- I just thought it was a neat idea. One aspect of this api I'd like to stick around for sure is the ability to access the data without a conditional and throwing an error when the data is missing. |
That's right currently for doing the submission of the form, behind the scene both And on Remix's Remix's 💡BTW: To go back on my argument; this particular handling is required for sending the form like a native
Remix's
The form might not be valid if it's submitted with some
What is making you so sure? I fail to understand the motivation or concrete use-case which can justify that despite all the exchanges we had. The only use-case I could see is to retrieve parsed data but there's way to do it as discussed before; but there's also caveats that any dev using Note: There's an open issue whatwg/xhr#262 which discuss a proposal that would include something such as |
I can't find any documentation specific to this. Adding |
Ah, that looks like an oversight. |
Thanks so much. Your efforts are appreciated! |
I wasn't able to find a way I was happy with that handled onBeforeSubmit: async (api) => {
if (api.sumitterOptions.formNoValidate) await api.performSubmit(api.unvalidatedData);
} This is an advanced / uncommon enough use-case that I'm satisfied with a slightly manual solution like this. |
What is the new or updated feature that you are suggesting?
Triggered by #139.
The attributes
novalidate
andformnovalidate
are standardized HTML attributes which can respectively be set on a<form>
or a submitter (<input>
,<button>
) to indicate that the form is not to be validated during submission. Their React JSX counterparts arenoValidate
andformNoValidate
.In
remix-validated-form
,noValidate
is used to disable native HTML validations to not conflict with the JS validation. It is currently recommended to use<ValidatedForm noValidate={useHydrated()}
to only use the native HTML validation when JS is disabled, when<ValidatedForm
is not hydrated. As forformNoValidate
, it is currently completely ignored.Therefore, there's currently no way to submit a
<ValidatedForm
without validation when it is hydrated.As discussed in #139,
noValidate
andnoFormValidate
would benefit by remaining closer to their web standard behavior as both – but especially the latter one – can be needed to implement certain use cases.As pointed by @airjp73 in #139 the following guidelines should however be followed:
I believe that desiring both
ValidatedForm
's validation and native HTML at the same time is highly unlikely. Each browser have a different implementation of how error messages are displayed, thus besides duplicating validation messages, the native UI would likely overlap withremix-validated-form
's errors and create a poor and confusing UX. Thus, I'd suggest making the disabling of native validation with<form novalidate
when<ValidatedForm
is hydrated an implementation detail.This would free up
noValidate
to fill the standard behavior of disabling ALL validation (JS and native HTML). And allowformNoValidate
to be supported with the same standard behavior.This however would represent a breaking change. Moreover, this could inadvertently end up breaking client-side validations if developers don't update their code where
<ValidatedForm noValidate={useHydrated()}
was used; as it was recommended. To help mitigate this, an idea could be to do a pre-minor release to implement aconsole.warn('⚠️ DEPRECATED usage of "noValidate" potentially detected, for more info please check http://...')
which would be raised whenever a change ofprops.noValidate
is detected during the hydration.Why should this feature be included?
novalidate
andformnovalidate
are web standard attributes that are expected to produce an established form behavior.I was set aback when I migrated
<form
or Remix's<Form
to<ValidatedForm
becauseformNoValidate
was not respected/supported.I believe that supporting both
noValidate
andnoFormValidate
with the standard behavior would make things more straightforward and simpler for developers. Otherwise, we have to rely on a workaround to intercept a click on a submitter to perform the submission without validation (e.g withuseFetcher
).Check https://codesandbox.io/s/rvf-y7jl8e?file=/app/routes/index.tsx for some code demoing an attempt to use
formNoValidate
in a<ValidatedForm
.The text was updated successfully, but these errors were encountered: