-
Notifications
You must be signed in to change notification settings - Fork 2.3k
liveValidate should optionally not validate "pristine" fields (at least until a submit) #512
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
Comments
I can't reproduce this behavior with the latest version. Maybe I'm missing a step? If not, how has this been fixed, that would been nice to know. |
This one is reproducible, though in this case we provide actual |
Ha ha, so apparently my browser had saved a password for localhost:8080 from when I was working on something two jobs ago, and it autofilled that password when I was hacking on rjsf. But obviously it didn't autofill the second one, so "passwords don't match". Never mind... |
The issue still surfaces for example if any of the fields in the "Validation" example are marked as required. In the example, the entire form lights up as the validation fails for the root element (the fieldset containing the fields). Any ideas on how to get rid of the |
This is a tough one. This example is a great use case for why you might want to live validate passwords as well as required fields, but it's not really great UX to show the user that fields later in the form aren't valid when they haven't even added anything to them. On the other hand, it doesn't make sense to wait until the user "touches" a required field to validate it, because the validation is the mere fact that it hasn't been touched. Here's an off-the-cuff idea for handling this: maybe we can maintain a state which indicates what the "latest" field that was touched was, and liveValidate only up to that? So for this example, when you enter pass1, we validate the password fields, and then when you get to age, we validate password fields plus the age, and then if you skip ahead to another field, we'd validate password, age, and everything up to the field you were on. I don't think we have the bandwidth to implement anything like this, but I'd try to review a PR.. |
Use I just provide a const formContext = {
lastUpdated: null,
formControlState: {},
setTouched: function (id) {
this.formControlState[id] = 'touched'
},
setDirty: function (id) {
this.formControlState[id] = 'dirty'
},
isTouched: function (id) {
return this.formControlState[id] === 'touched'
},
isPristine: function (id) {
return this.formControlState[id] == null
},
isDirty: function (id) {
return this.formControlState[id] === 'dirty'
}
} I just curry the validate function and pass this const validate = (formContext, formData, errors) => {
const {password, confirm} = formData
// hard coding confirm id
const confirmId = 'root_confirm'
const confirmModified =
formContext.isTouched(confirmId) || formContext.isDirty(confirmId)
if (password != null && confirmModified) {
if (password !== confirm) {
// errors.password.addError("Passwords don't match")
errors.confirm.addError("Passwords don't match")
}
}
return errors
} Create a higher order component for widgets and fields, do a custom However, I cannot get the name of the field within formData here and must resort to using an Additionally, I am finding it hard to show error on confirm only confirm when password or confirm has been updated (in the example above) so maybe the idea of fields within uiSchema would make sense so that validation occurs only when related fields are changed. Then we can validate using: const canShowErrors =
!isPristine(id) && (id === lastUpdated || isRelatedField) inside the |
I just came across this issue too. My form instantly has errors when no fields have been manipulated. |
@vamsiampolu How would your solution address "required" fields that the user skips over? I agree that validating only "touched" fields is necessary, but not sufficient. |
Imho live validation should be trigger if a input control looses focus.
The latter one is a nice thing, as often while typing the editor is in an invalid state (password does not yet match, string is not yet an email-address, and so on) |
IMHO, instead of modifying the validate function, its better to show or hide errors based on touched or not. A field should always be invalid if it does not have valid data irrespective of touched or not. However, the error message display need not happen if its not touched. |
Sounds like this discussion is on the right track. @rsaiprasad @jannikbuschke are you interested in making a PR that implements this change? |
Where is this at? Would be nice to only validate touched fields! Happy to get involved if there is a branch open otherwise I can start one. Really would like this feature so I can improve the POC and actually get this library approved for our project going forward. |
I would to be willing to work on it as well, I am also in need of this functionality for my project. |
Feel free to submit a PR / start a branch to work on this issue. It would be good to get it into v2 because it would probably entail a breaking change. |
To clarify, I think invalid fields that have not been touched yet would need to wait until submit before they showed their error messages. |
Two years pasted and any update on this issue? |
Good news for the issue followers, I code a fix of this issue. |
@calpa cool, would you like to make a PR? |
@epicfaace I think this is a demo instead of code changes, so need PR? |
Would be great to have some resolution on this problem, its been open since 2017 and I would consider this a fairly fundamental feature for live-validation to work in a sane way. |
Any updates on this? It's 2021 now! |
It's been over 4 years since this request to support very commonly-implemented form functionality. I'm not sure why it isn't a higher priority. Is this issue ever going to be addressed? @epicfaace ? |
… On Wed, Aug 18, 2021, 1:54 PM Samantha ***@***.***> wrote:
It's been over 4 years since this request to support very
commonly-implemented form functionality. I'm not sure why it isn't a higher
priority. Is this issue ever going to be addressed? @epicfaace
<https://github.com/epicfaace> ?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#512 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAM4MX3LFD3WHL3SGKFFBATT5PXVPANCNFSM4DDTQ3KA>
.
|
Might be useful for someone. Solved a similar problem using a form ref and transformErrors function. // simplified example
function transformErrors(form: Form<any>) {
// @ts-expect-error
const formData = form?.state?.formData ?? {};
return (errors: AjvError[]) => (
errors.reduce((errorsList, error) => {
const isPropDirty = error.property.slice(1) in formData;
return isPropDirty ? [...errorsList, error] : errorsList;
}, [])
)
}
const TemplateForm = (formProps) => {
// WARN: not sure which type is correct for form ref
const formRef = useRef<Form<any>>();
return (
<Form
{...formProps}
ref={formRef}
liveValidate
transformErrors={transformErrors(formRef.current)}
/>
} |
Thank you @theexplay for the good work, I think |
@theexplay Hi.., can you produce the same in code Sandbox ? i am not getting the exact behaviour as shown in the attached GIF. Just want to check what i am missing to get the similar behaviour. |
@Dave-Rushabh sure - https://codesandbox.io/s/serene-archimedes-px0skd?file=/src/TemplateForm.tsx (simplified version from code) I have wrapper with form data controlled, on change data fire to change state, it rerender Form component and useRef value updated, smth like this) |
@theexplay This works!! Thank you brother.. |
But in this case, when we click submit button on the empty form (not touching any fields), we don't see any errors. Especially when I wonder if we can somehow determine if validation process called from liveValidation or from submit. If this possible, then we could show all errors on submit and only touched fields on live validation. |
Thanks to @theexplay , I solved my problem. Now the error list remains hidden until the first submit, and I won't submit if there are any errors even for the first submit. Example: const CompiledForm = (props: {
onSubmit: () => void;
//... props
}) => {
//... business logic
const formRef = useRef<Form>(null);
// You have to use Ref here, or ths transformErrors will still return [] on first submit
// which make validation failed on the first submit
const hasSubmittedRef = useRef(false);
const transformErrors = useCallback(
(errors: RJSFValidationError[]) => (hasSubmittedRef.current ? errors : []),
[]
);
return (
<Form
// ...
onSubmit={() => {
hasSubmittedRef.current = true;
if (!formRef.current?.validateForm()) {
return;
}
onSubmit();
}}
liveValidate={true}
transformErrors={transformErrors}
>
{/* Business Button */}
</Form>
);
}; |
Prerequisites
Description
In the playground, the "Validation" tab, when live validation is enabled, starts with an error ("passwords don't match"). However, the user hasn't put in a password yet, so it doesn't make sense as part of the user experience to show this error, at least until they start typing in the field.
Similarly, in the "Errors" tab, the initial state shows a bunch of errors. However, for some user experiences, this doesn't seem necessary or helpful; we're telling the user about errors that pre-existed, not errors they themselves have made.
Per #246 (comment), maybe we should not validate fields until they've been "touched" somehow.
The text was updated successfully, but these errors were encountered: