createForm

API for the createForm function

createForm

This is a client side form, for server side actions check out the createForm$ function.

The createForm utility is being used to create a form and interact with the MediaKit/Forms api.

import { z } from 'zod'
import { createForm } from '@solid-mediakit/forms'

const { RenderTestForm, testFieldErrors } = createForm({
  schema: z.object({
    name: z.string().min(1),
    test: z.string().min(1),
  }),
  name: 'test',
})

CreateForm Input

The createForm function accepts in 3 properties

schema (required)

const {} = createForm({
  schema: z.object({
    name: z.string().min(1),
    test: z.string().min(1),
  }),
  ...
})

name (optional)

Specifying a name is going to change all of your returned variables names

const { RenderTestForm } = createForm({
  name: 'test',
  ...
})

// no name

const { RenderForm } = createForm({...})

defaultValues (optional)

const {} = createForm({
  defaultValues: {
    name: 'default name',
    test: 'default test',
  },
  ...
})

Variables Name

The returned variables names changed based on the name mentioned in the createForm input.

// name: test
const { RenderTestForm, testFieldErrors, TestField } = createForm({
  schema: z.object({ name: z.string().min(1), test: z.string().min(1) }),
  name: 'test',
})

// name: ok
const { RenderOkForm, okFieldErrors, OkField } = createForm({
  schema: z.object({ name: z.string() }),
  name: 'ok',
})

// no name
const { RenderForm, fieldErrors, Field } = createForm({
  schema: z.object({ name: z.string() }),
})

Once created a form, you will be given a function to render the Form automatically, but you will also be given a Field component you could use to render the <form> element on your own.

RenderForm

This is the recommended way of rendering a form, all you need is to render the RenderForm component you received from the createForm function.

import { type VoidComponent } from 'solid-js'
import { z } from 'zod'
import { createForm } from '@solid-mediakit/forms'

const Home: VoidComponent = () => {
  const { RenderExampleForm, exampleFieldErrors } = createForm({
    schema: z.object({
      name: z.string().min(1),
      test: z.string().min(1),
    }),
    name: 'example',
  })
  return (
    <RenderExampleForm
      onSubmit={async (input) => console.log(input)}
      onFormError={(e) => {
        if (e.isZodError()) {
          const nameErros = e.cause.fieldErrors.name // string[] | undefined
          const testErrors = e.cause.fieldErrors.test // string[] | undefined
          console.log('Validation error', { nameErros, testErrors })
        } else {
          console.log(e.cause)
        }
      }}
      class='flex p-3 rounded-lg flex-col gap-2 h-[300px] w-[80vw] bg-zinc-800 items-center'
    >
      {({ Field, name }) => {
        // name: name | 'test
        const bgColor = name === 'test' ? 'bg-gray-700' : 'bg-zinc-900'
        return (
          <Field
            inputClass={`${bgColor} p-3 rounded-lg focus:outline-none text-gray-500`}
            labelClass='text-white font-bold text-lg'
            wrapperClass='flex flex-col gap-1'
          />
        )
      }}
      <button class='bg-zinc-900 w-[80%] font-bold rounded-lg p-3 text-white flex items-center justify-center'>
        My Submit
      </button>
    </RenderExampleForm>
  )
}

export default Home

onSubmit

This function will be called with a type-safed required input after validation the input using the provided schema.

<RenderExampleForm
  onSubmit={async (input) => {
    console.log(input) // {name: string; test: string;}
  }}
>
{...}
</RenderExampleForm>

onFormError

This function will be called whenever the schema failed to validate the input.

<RenderExampleForm
  onFormError={(e) => {
    if (e.isZodError()) {
      const nameErros = e.cause.fieldErrors.name // string[] | undefined
      const testErrors = e.cause.fieldErrors.test // string[] | undefined
      console.log('Validation error', { nameErros, testErrors })
    } else {
      console.log(e.cause)
    }
  }}
>
{...}
</RenderExampleForm>

validate

This function returned from createForm is a function you can use to validate your data manually (i.e when you don’t want to use RenderForm).

<form
  onSubmit={async (e) => {
    e.preventDefault()
    e.stopPropagation()
    const [success, dataOrError] = await validateTest()
    if (success) {
      console.log('is data', dataOrError)
      // do stuff
    } else {
      console.log('is error', dataOrError)
    }
  }}
></form>

Notice again: the name of the variables change based on the name property mention in the createForm input.

Field

You can also create your own forms and use our validation & type-safed Field component

import { Show, type VoidComponent } from 'solid-js'
import { z } from 'zod'
import { createForm } from '@solid-mediakit/forms'

const styles = {
  inputClass: 'p-3 bg-zinc-900 rounded-lg focus:outline-none text-gray-500',
  labelClass: 'text-white font-bold text-lg',
  wrapperClass: 'flex flex-col gap-1',
}

const Home: VoidComponent = () => {
  const { testFieldErrors, TestField, validateTest } = createForm({
    schema: z.object({
      name: z.string().min(1),
      test: z.string().min(1),
    }),
    name: 'test',
  })
  return (
    <div>
      <Show when={testFieldErrors()}>
        {(e) => {
          return <pre>{JSON.stringify(e(), null, 2)}</pre>
        }}
      </Show>
      <form
        onSubmit={async (e) => {
          e.preventDefault()
          e.stopPropagation()
          const [success, dataOrError] = await validateTest(e.target)
          if (success) {
            console.log('is data', dataOrError)
            // do stuff
          } else {
            console.log('is error', dataOrError)
          }
        }}
      >
        <TestField name='test' {...styles} />
        <TestField name='name' {...styles} />
        <button type='submit'>My Submit</button>
      </form>
    </div>
  )
}

export default Home

Styling

When using the Field component, you can choose to style it however you like:

  • inputClass - The class of the input element
  • labelClass - The class of the label element
  • wrapperClass - The class of the div that wraps the input and label elements.
<Field
  inputClass='p-3 rounded-lg focus:outline-none text-gray-500'
  labelClass='text-white font-bold text-lg'
  wrapperClass='flex flex-col gap-1'
/>

Note: This is also relevent to the Field component you receieve when using the RenderForm method.

fieldErrors

The createForm function returns a signal that contains the errors of the input, so we can also do something like:

<Show when={exampleFieldErrors()}>
  {(e) => {
    return <pre>{JSON.stringify(e(), null, 2)}</pre>
  }}
</Show>

Notice again: the name of the variables change based on the name property mention in the createForm input.

values

The createForm function also returns a signal that contains the current forms values, so we can use a SolidJS effect to render the current values.

const { testValues } = createForm({
  schema: z.object({
    name: z.string().min(1),
    test: z.string().min(1),
  }),
  name: 'test',
  defaultValues: {
    name: 'default name',
    test: 'default test',
  },
})

createEffect(() => {
  console.log(testValues())
})