Git Product home page Git Product logo

Comments (3)

Ashyni avatar Ashyni commented on May 27, 2024 3

Hello, I end up with something like that to reuse on different form/action.

//@types/action.d.ts
import { FieldValues, FormErrors } from "@modular-forms/solid";
import { Action } from "@solidjs/router";

export type ActionForm<Schema extends FieldValues> = Action<
  [data: Schema],
  { success?: boolean; error?: string; fields?: FormErrors<Schema> } | void
>;
// autocomplete on fields from TS
//lib/utils.ts
export function flatIssues<K extends string | number>(
  issues: SchemaIssues,
): { [key in K]?: string } {
  let errors: { [key in K]?: string } = issues ? {} : {};

  return issues.reduce((acc, issue) => {
    if (
      issue.path?.every(
        ({ key }) => typeof key === "string" || typeof key === "number",
      )
    ) {
      const key = issue.path!.map(({ key }) => key).join(".") as K;
      if (acc[key]) {
        acc[key] = acc[key] + "\n" + issue.message; // merge multiple issues, split in components
      } else acc[key] = issue.message;
    }
    return acc;
  }, errors);
}
//login.tsx
export default function Index() {
  const action = useAction(login);
  const submission = useSubmission(login);
  const [loginForm, { Form, Field }] = createForm<LoginForm>({
    validate: valiForm(LoginSchema),
  });
  const handleSubmit: SubmitHandler<LoginForm> = async (values) => {
    await action(values);
    if (submission.result) {
      const { error = "", fields = {} } = submission.result;
      throw new FormError<LoginForm>(error, fields);
    }
  };
  return ( ... );
};

const LoginSchema = v.object({ ... })
type LoginForm = v.Input<typeof LoginSchema>;

const login: ActionForm<LoginForm> = action(async (data) => {
  "use server";
  const result = v.safeParse(LoginSchema, data);
  if (!result.success) {
    const errors = flatIssues<keyof LoginForm>(result.issues);
    return { fields: errors };
  }

  const { username, password } = result.output;

  // db call
  if (failed) return { error: "user does not exist" };

  // all good
  throw redirect("/");
}, "login");

from modular-forms.

CallumVass avatar CallumVass commented on May 27, 2024

Okay I think I've figured it out but it seems a bit quirky, please let me know if there is a better way?

Action code:

const login = action(async (values: LoginForm) => {
  "use server";

  const result = safeParse(LoginSchema, values);
  if (!result.success) {
    const flattened = flatten<typeof LoginSchema>(result.issues);
    const errors = Object.entries(flattened.nested).reduce(
      (acc, [key, value]) => {
        acc[key] = value[0];
        return acc;
      },
      {} as { [key: string]: string },
    );

    if (flattened.root && flattened.root.length > 0) {
      return new FormError<LoginForm>(flattened.root[0], errors);
    }

    return new FormError<LoginForm>(errors);
  }

  return new FormError<LoginForm>("Email exists in database");
});

Submit code:

  const [loginForm, { Form, Field }] = createForm<LoginForm>({});
  const act = useAction(login);
  const sub = useSubmission(login);
  const handleSubmit: SubmitHandler<LoginForm> = async (values) => {
    await act(values);
    if (sub.result) {
      Object.entries(sub.result.errors).forEach(([field, message]) => {
        setError(loginForm, field as keyof LoginForm, message);
      });
      throw new FormError<LoginForm>(sub.result.message);
    }
  };

from modular-forms.

fabian-hiller avatar fabian-hiller commented on May 27, 2024

Hey, I haven't had time to take a closer look at the new SolidStart beta release. I plan to integrate it in the future with a nice API and DX, but that will take some time.

from modular-forms.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.