Skip to content
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

How to validate if the field has been changed using valiForm$? #239

Open
genki opened this issue Aug 19, 2024 · 11 comments
Open

How to validate if the field has been changed using valiForm$? #239

genki opened this issue Aug 19, 2024 · 11 comments
Assignees
Labels
question Further information is requested

Comments

@genki
Copy link

genki commented Aug 19, 2024

I am making Qwik app that uses modular-forms with valibot.
I have tried to make valibot schema that validates if the field of the form has been changed.
But the Qwik doesn't permit the use of local variables, the valibot schema should be located at the module scope.
So I think there is no way to provide the initial value to the schema, that is needed for that validation.

Is there a way to inject the initial value to the valibot schema?

@fabian-hiller
Copy link
Owner

I don't think this is currently possible. 😐

@fabian-hiller fabian-hiller self-assigned this Aug 20, 2024
@fabian-hiller fabian-hiller added the question Further information is requested label Aug 20, 2024
@genki
Copy link
Author

genki commented Aug 20, 2024

I see. Finally I have solved my issue like this.

    validate:$<ValidateForm<Some>>(async values => {
      const {issues} = await safeParseAsync(
        SomeSchema, values, {abortEarly:true});
      const formErrors: Record<string, string> = {};
      if (issues) {
        for (const issue of issues) {
          formErrors[getDotPath(issue)!] = issue.message;
        }
      }
      const {body} = values;
      if (body === loaded.value.body) {
        formErrors.body = "Not changed";
      }
      return formErrors;
    }),

I think it is not rare case that the validation on relationship between the initial (current) values and input values.
How about to add the second argument to the valiForm$ to provide custom validator QRL like above?
As using that, the above to be like this;

    validate:valiForm$(SomeSchema, $(({body}, errors) => {
      if (body === loaded.value.body) errors.body = "Not changed";
    }),

@fabian-hiller
Copy link
Owner

I need more context. What is loaded? Why it is necessary to access this object? Can you send me a minimal reproduction via StackBlitz?

@genki
Copy link
Author

genki commented Aug 20, 2024

I sent a PR. pls look at that.

@genki
Copy link
Author

genki commented Aug 20, 2024

@fabian-hiller Currently the modular-form couldn't treat the validation that need to refer the initial value of the form, so I couldn't show it on the stackbliz.
The context as follows:

I needed to check the update of a field of the form.
I wanted if it is not changed, show error to the form.
The initial values are loaded by using routeLoader$ of the Qwik.
If I use the valiForm$ as the validater of the form, there is no way to validate the change/update of a field of the form.
The only way to do it is using custom validater QRL including the validation steps of the validForm$'s.
But it is hassle, I would like to add the function to the valiForm$.

@genki
Copy link
Author

genki commented Aug 20, 2024

Giving a real example, suppose the edit form of the blog post.
We have to avoid to submit without the change.
The current blog text is the initial value of a field of the form, this is loaded by the routeLoader$.
I think this situation is common, but current valiForm$ is not useful for such cases.

@fabian-hiller
Copy link
Owner

I don't quite understand the use case. Do you want to send the form only when it is "dirty" and contains changes?

@genki
Copy link
Author

genki commented Aug 23, 2024

@fabian-hiller Partially Yes. The dirty state should exist not only for the entire form but for the certain field or fields.
For the case of the editing a blog post, it is not valid if the change is consists of only hidden fields such as CSRF token.

@fabian-hiller
Copy link
Owner

There is a dirty state for each field. If I have a minimal StackBlitz reproduction, I can check if what you want is already possible. At the moment I am not interested in extending the functionality of Modular Forms because Valibot has a higher priority and the moment and I may rewrite Modular Forms anyway.

@genki
Copy link
Author

genki commented Aug 27, 2024

@fabian-hiller The problem is a bit complicated for making example on the StackBlitz.
So I provide a running example that is using the modular-forms with valiForm$ (with my patch applied)
https://twpro.jp/twprofile
I couldn't make this form validation without my PR #240

The part relating with the validation goes like this:

  const [form, {Form, Field}] = useForm({
    loader:{value: {
      id:undefined as number|undefined,
      form_id:app.account?.form_id ?? undefined,
      body:app.account?.form_body,
      email:undefined as string|undefined,
      email_ok:undefined as boolean|undefined,
      privacy:false as boolean,
    }},
    validate:valiForm$(InquirySchema, $(async (
      {body, email, privacy}:Partial<Inquiry>, errors:FormErrors<Inquiry>
    ) => {
      if (body === app.account?.form_body) {
        errors.body = "フォームに内容を記入してください";
      }
      if (email && !privacy) {
        errors.privacy = "プライバシーポリシーに同意頂く必要があります。";
      }
    })),
  })

@fabian-hiller
Copy link
Owner

Sorry for not getting back to this at the same pace I usually do, but at the moment I can't find the time to investigate this further. I will try to come back later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants