nuxt / nuxt/ui

[Form] Composable to generate state based on a standard schema

Open
#3,876 14 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

triage
Dominant language
TypeScript
Stars
6.9k
Forks
1.1k
Avg merge
1d 7h
Merged PRs (30d)
57

Description

Description

Hey!

Currently, the form component requires defining a schema and a state. This means we need to duplicate each form field twice.

<script setup lang="ts">
  import * as z from 'zod'
  
  const schema = z.object({
    email: z.string().email('Invalid email'),
    password: z.string().min(8, 'Must be at least 8 characters')
  })
  
  type Schema = z.output<typeof schema>
  
  // We have to repeat the keys again to define the state
  const state = reactive<Partial<Schema>>({
    email: undefined,
    password: undefined
  })
</script>

<template>
  <UForm :schema :state>
    ...
  </UForm>
</template>
Proposed Solution

Having a composable similar to that takes a standard validation object and returns both the schema and state will be much better DX. Below is the refactored version of the above example using the requested composable.

<script setup lang="ts">
  import * as z from 'zod'
  
  // Both `state` and `schema` are typed. `state` is also reactive
  const { state, schema } = useForm({
    schema: {
      email: z.string().email('Invalid email'),
      password: z.string().min(8, 'Must be at least 8 characters')
    },
    initialValues, {
      email: 'foo@bar.com'
    }
  })
</script>

<template>
  <UForm :schema :state>
    ...
  </UForm>
</template>
VeeValidate

This is similar to how useForm and toTypedSchema composables from VeeValidate (source)

import { useForm } from 'vee-validate';
import { object, string } from 'zod';
import { toTypedSchema } from '@vee-validate/zod';

// `values` is the equivalent of `state` in nuxt/ui
const { values } = useForm({
  validationSchema: toTypedSchema(
    object({
      email: z.string().email('Invalid email'),
      password: z.string().min(8, 'Must be at least 8 characters')
    }),
  ),
});

The problem with integrating VeeValidate instead of a built-in helper is the values ref. It's the equivalent of state ref in nuxt/ui, which we pass to the UForm component to be mutated. VeeValidate discourages mutating values directly (docs).

Possible Workaround

Provide docs on how to integrate VeeValidate or similar libraries that return a typed schema and a state ref in one go.

Additional context

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No implementation files or tests are named. Start by reviewing the existing UForm schema and state API, then compare the proposed useForm shape with the VeeValidate examples in the issue. Done means a decided, typed composable design that produces reactive state and a validation schema, or clear integration documentation if a built-in helper is not pursued.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.