Skip to content
Andreas Söderlund edited this page Mar 20, 2023 · 32 revisions

Types

Throughout the reference, the following types are represented:

// T represents the validation schema z.object({ ... })
T extends AnyZodObject

// S refers to the underlying type of the schema, the actual data structure.
S = z.infer<T>

// Nested represents a structure where the values in S are replaced with the second parameter.
Nested<S, string[] | undefined> // Errors for each field in S
// HTML input constraints returned from superValidate
export type InputConstraints = Partial<{
  pattern: string;
  min: number | string;
  max: number | string;
  required: boolean;
  step: number;
  minlength: number;
  maxlength: number;
}>
// The return value from superValidate
export type Validation<T, M = any> = {
  valid: boolean;
  data: S;
  errors: Nested<S, string[] | undefined>;
  empty: boolean;
  constraints: Nested<S, InputConstraints | undefined>;
  message?: M;
  id?: string;
  meta?: { types: Record<keyof S, string> }
};

Server API

import {
  superValidate,
  setError,
  noErrors,
  actionResult
} from 'sveltekit-superforms/server';

superValidate(data, schema, options?)

superValidate<T extends AnyZodObject, M = any>(
  data:
    | RequestEvent
    | Request
    | FormData
    | Partial<S>
    | null
    | undefined,
  schema: T | ZodEffects<T>, // refine/superRefine/transform
  options?: {
    noErrors = false;    // Remove errors from output (but keeps valid status)
    includeMeta = false; // Add metadata to the validation entity:
    id?: string          // Form id, for multiple forms support:
  }
): Promise<Validation<T, M>>

If data is determined to be empty (null, undefined or no FormData), a validation result with a default entity for the schema is returned, in this shape:

{
  valid: false;
  errors: {};
  data: S; // See further down for default entity values.
  empty: true;
  message: undefined;
  constraints: Nested<S, InputConstraints>;
  meta?: { types: Record<keyof S, string> }
}

setError(form, field, error, options?)

setError(
  form: Validation<T>,
  field: keyof S | [keyof S, ...(string | number)[]],
  error: string | string[],
  options?: { overwrite = false, status = 400 }
) : ActionFailure<{form: Validation<T>}>

If you want to set an error on the form outside validation, use setError. It returns a fail(status, { form }) so it can be returned immediately, or more errors can be added by calling it multiple times before returning. Use the overwrite option to remove all previously set errors for the field, and status to set a different status than the default 400.

noErrors(form)

If you want to return a form with no validation errors. Only the errors property will be modified, so valid still indicates the validation status. Can be useful for load functions where the entity is invalid, but as an initial state no errors should be displayed on the form.

noErrors(form: Validation<T>) : Validation<T>

actionResult(type, data?, status?)

When using endpoints instead of form actions, you must return an ActionResult, throw redirect(...) won't work directly since superForms expects an ActionResult. This method helps you construct one in a Response object, so you can return a validation object from your API/endpoints.

// Every call can take a http status as a third parameter.
actionResult('success', { form })
actionResult('failure', { form })
actionResult('redirect', '/')
actionResult('error', 'Error message')

Example for a login request:

src/routes/login/+server.ts

import { actionResult, superValidate } from '$lib/server';
import { z } from 'zod';
import type { RequestHandler } from './$types';

const loginSchema = z.object({
  email: z.string().email(),
  password: z.string().min(5)
});

export const POST = (async (event) => {
  const form = await superValidate(event, loginSchema);
  if (!form.valid) return actionResult('failure', { form });

  // Verify login here //

  return actionResult('success', { form });
}) satisfies RequestHandler;

Client API

import {
  superForm,
  intProxy,
  numberProxy,
  booleanProxy,
  dateProxy
} from 'sveltekit-superforms/client';

superForm(form, options?)

superForm<T, M = any>(
  form: Validation<T, M> | null | undefined,
  options?: FormOptions<T, M>
) : EnhancedForm<T, M>
FormOptions<T extends AnyZodObject, M> = Partial<{
  id: string;
  applyAction: boolean;
  invalidateAll: boolean;
  resetForm: boolean;
  scrollToError: 'auto' | 'smooth' | 'off';
  autoFocusOnError: boolean | 'detect';
  errorSelector: string;
  stickyNavbar: string;
  taintedMessage: string | false | null;
  onSubmit: (
    ...params: Parameters<SubmitFunction>
  ) => MaybePromise<unknown | void>;
  onResult: (event: {
    result: ActionResult;
    formEl: HTMLFormElement;
    cancel: () => void;
  }) => MaybePromise<unknown | void>;
  onUpdate: (event: {
    form: Validation<T, M>;
    cancel: () => void;
  }) => MaybePromise<unknown | void>;
  onUpdated: (event: {
    form: Validation<T, M>;
  }) => MaybePromise<unknown | void>;
  onError:
    | 'apply'
    | ((event: {
        result: {
          type: 'error';
          status?: number;
          error: App.Error;
        };
        message: Writable<Validation<T, M>['message']>;
      }) => MaybePromise<unknown | void>);
  dataType: 'form' | 'json';
  validators: Validators<T> | T;
  defaultValidator: 'keep' | 'clear';
  clearOnSubmit: 'errors' | 'message' | 'errors-and-message' | 'none';
  delayMs: number;
  timeoutMs: number;
  multipleSubmits: 'prevent' | 'allow' | 'abort';
  flashMessage: {
    module: {
      getFlash(page: Readable<Page>): Writable<App.PageData['flash']>;
      updateFlash(
        page: Readable<Page>,
        update?: () => Promise<void>
      ): Promise<void>;
    };
    onError?: (event: {
      result: {
        type: 'error';
        status?: number;
        error: App.Error;
      };
      message: Writable<App.PageData['flash']>;
    }) => MaybePromise<unknown | void>;
    cookiePath?: string;
  };
}>;

superForm return type

EnhancedForm<T extends AnyZodObject, M = any> = {
  form: Writable<Validation<T, M>['data']>;
  errors: Writable<Validation<T, M>['errors']>;
  constraints: Writable<Validation<T, M>['constraints']>;
  message: Writable<Validation<T, M>['message']>;
  meta: Readable<Validation<T, M>['meta']>;

  valid: Readable<boolean>;
  empty: Readable<boolean>;
  submitting: Readable<boolean>;
  delayed: Readable<boolean>;
  timeout: Readable<boolean>;

  fields: FormFields<T>;
  firstError: Readable<{ path: string[]; message: string } | null>;
  allErrors: Readable<{ path: string[]; message: string }[]>;

  tainted: Readable<TaintedFields<T> | undefined>;

  enhance: (el: HTMLFormElement) => ReturnType<typeof formEnhance>;
  update: FormUpdate;
  reset: (options?: { keepMessage: boolean }) => void;
};

intProxy(form, fieldName)

Creates a proxy store for an integer form field. Changes in either the proxy store or the form field will reflect in the other.

numberProxy(form, fieldName)

Creates a proxy store for a numeric form field. Changes in either the proxy store or the form field will reflect in the other.

booleanProxy(form, fieldName, { trueStringValue = 'true' })

Creates a proxy store for a boolean form field. Changes in either the proxy store or the form field will reflect in the other. The option can be used to change what string value represents true.

dateProxy(form, fieldName, { format: 'date-local' | 'datetime-local' | 'time-local' | 'iso' = 'iso' )

Creates a proxy store for a boolean form field. Changes in either the proxy store or the form field will reflect in the other. The option can be used to format the string value differently, based on the input type for example.

Proxy example

Given the following schema:

const schema = z.object({
  date: z.date()
})

A proxy can be used like this:

<script lang="ts">
  import { superForm, dateProxy } from 'sveltekit-superforms/client'
  import type { PageData } from './$types';

  export let data: PageData;

  const form = superForm(data.form)
  const date = dateProxy(form, 'date', { format: 'date-local' ))
</script>

<input name="date" type="date" bind:value={$date} />

Components

import SuperDebug from 'sveltekit-superforms/client/SuperDebug.svelte';

SuperDebug

SuperDebug gives you a colorized and formatted JSON output for any data structure, but usually $form.

<SuperDebug
  data={any}
  display?={true}
  label?={""}
  promise?={false}
  status?={true}
  stringTruncate?={120}
  ref?={HTMLPreElement}
/>

SuperDebug props

Prop Type Default value Description
data any undefined Data to be displayed by SuperDebug
display Boolean true Whether to show or hide SuperDebug
label String "" Add useful label to SuperDebug, useful when using multiple instances of SuperDebug in a page
promise Boolean false When true, SuperDebug uses svelte's await block to load the data. Data is assumed to be async but can also load non-async data using await block!
status Boolean true Whether to show or hide status code.
stringTruncate Number 120 Truncate long string in output.
ref HTMLPreElement undefined Binds pre tag to ref.

SuperDebug usage

Please see the +page.svelte file in src/routes/super-debug on common usage of SuperDebug.

https://github.com/ciscoheat/sveltekit-superforms/tree/main/src/routes/super-debug

Clone this wiki locally