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

feature: add formData schema #81

Closed
Yovach opened this issue Aug 8, 2023 · 6 comments · May be fixed by #539
Closed

feature: add formData schema #81

Yovach opened this issue Aug 8, 2023 · 6 comments · May be fixed by #539
Assignees
Labels
enhancement New feature or request wontfix This will not be worked on

Comments

@Yovach
Copy link
Contributor

Yovach commented Aug 8, 2023

Hi,
I don't know how this would affect bundle size, but I think it would be interesting to have an API like :

const reportSchema = formData({
  title: string(),
  content: string(),
  photo: file(),
});

It could be useful in server actions (Next.js) and client-side validations in <form>.

@fabian-hiller
Copy link
Owner

I think the idea is cool, but I don't know yet how much sense it makes, because as far as I know FormData can't be typed. Probably the better approach would be to use object and convert FormData to an object before validation.

@fabian-hiller fabian-hiller self-assigned this Aug 8, 2023
@fabian-hiller fabian-hiller added the enhancement New feature or request label Aug 8, 2023
@fabian-hiller
Copy link
Owner

Here is a code example:

import { email, minLength, object, parse, string } from "valibot"; // 0.75 kB
import { loginUser } from "~/api";

const LoginSchema = object({
  email: string([
    minLength(1, "Please enter your email."),
    email("The email address is badly formatted."),
  ]),
  password: string([
    minLength(1, "Please enter your password."),
    minLength(8, "You password must have 8 characters or more."),
  ]),
});

export default function LoginRoute() {
  async function login(formData: FormData) {
    "use server";
    try {
      const { email, password } = parse(
        LoginSchema,
        Object.fromEntries(formData.entries())
      );
      await loginUser({ email, password });
    } catch (error) {
      // Handle errors
    }
  }

  return (
    <form action={login}>
      <input name="email" type="email" required />
      <input name="password" type="password" required minLength={8} />
      <button type="submit">Login</button>
    </form>
  );
}

@Yovach
Copy link
Contributor Author

Yovach commented Aug 8, 2023

Here is a code example:

import { email, minLength, object, parse, string } from "valibot"; // 0.75 kB
import { loginUser } from "~/api";

const LoginSchema = object({
  email: string([
    minLength(1, "Please enter your email."),
    email("The email address is badly formatted."),
  ]),
  password: string([
    minLength(1, "Please enter your password."),
    minLength(8, "You password must have 8 characters or more."),
  ]),
});

export default function LoginRoute() {
  async function login(formData: FormData) {
    "use server";
    try {
      const { email, password } = parse(
        LoginSchema,
        Object.fromEntries(formData.entries())
      );
      await loginUser({ email, password });
    } catch (error) {
      // Handle errors
    }
  }

  return (
    <form action={login}>
      <input name="email" type="email" required />
      <input name="password" type="password" required minLength={8} />
      <button type="submit">Login</button>
    </form>
  );
}

Yes, in this case it's sufficient, but when we need to upload files, we have to encode the file in base64 on the client side, then decode the base64 on the server side to check the size and buffer, so it's quite redundant. A great library exists in zod for these cases, but its implementation seems heavy.

@fabian-hiller
Copy link
Owner

It is not a good idea to convert a file to base64. Instead the native functionality of the <form /> element should be used. I think that it is currently better for Valibot to focus on validation and leave this functionality to other libraries for now.

In fact, I have already implemented such a function for Modular Forms that can handle even complex objects and arrays: https://github.com/fabian-hiller/modular-forms/blob/main/packages/qwik/src/utils/getFormDataValues.ts

@fabian-hiller fabian-hiller added the wontfix This will not be worked on label Aug 8, 2023
@Yovach
Copy link
Contributor Author

Yovach commented Aug 9, 2023

It is not a good idea to convert a file to base64. Instead the native functionality of the <form /> element should be used. I think that it is currently better for Valibot to focus on validation and leave this functionality to other libraries for now.

In fact, I have already implemented such a function for Modular Forms that can handle even complex objects and arrays: https://github.com/fabian-hiller/modular-forms/blob/main/packages/qwik/src/utils/getFormDataValues.ts

Yeah I know that it's not a good idea to convert file to base64 but tRPC did not accept FormData :/

Thanks for your reply, I'm closing this ticket.

@Yovach Yovach closed this as completed Aug 9, 2023
@fabian-hiller
Copy link
Owner

Yeah I know that it's not a good idea to convert file to base64 but tRPC did not accept FormData :/

I was not aware of that. If there is no other way, I understand the approach. Because of the modularity of Valibot, this functionality can be added quite easily. If someone starts a project for this that builds on Valibot, I'll be happy to link it on our ecosystem page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request wontfix This will not be worked on
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants