Tainted fields

When the form data is modified, through modifying $form, the modified data (and in turn the form), is considered tainted, also known as “dirty” in other form libraries.

A Superforms feature is to prevent the user from losing data when navigating away from a tainted form.


const { form, enhance } = superForm(data.form, {
  taintedMessage: string | (() => Promise<boolean>) | boolean = false

You can set the option to true to have a default message (in english) shown when navigating away from a tainted form, or set your own message with a string value. Note that this message will only be displayed when navigating to a page within the same site. When closing the tab or reloading the page, a browser default message will be shown instead.

Alternatively, you can set taintedMessage to a () => Promise<boolean> function that should resolve to true if navigating away is ok. This enables you to provide your own dialog:

const { form, enhance } = superForm(data.form, {
  taintedMessage: () => {
    return new Promise((resolve) => {
        type: 'confirm',
        title: 'Do you want to leave?',
        body: 'Changes you made may not be saved.',
        response: resolve

The code demonstrates the custom dialog with a Skeleton modal. Try it out below! Modify the form, then click the back button. A modal should pop up, preventing you from losing the changes:

Untainting the form

When a successful validation result is returned for the form, with a valid status set to true, the form is automatically marked as untainted.

Try that by posting the form with valid values. The tainted message should not appear when browsing away from the page.

Check if the form is tainted

An isTainted method is available on superForm, to check whether any part of the form is tainted:

<script lang="ts">
  const { form, enhance, tainted, isTainted } = superForm(form.data);

  // Check the whole form
  if(isTainted()) {
    console.log('The form is tainted')

  // Check a part of the form
  if(isTainted('name')) {
    console.log('The name field is tainted')

<!-- Make the function reactive by passing the $tainted store -->
<button disabled={!isTainted($tainted)}>Submit</button>

<!-- It even works with individual fields -->
<button disabled={!isTainted($tainted.name)}>Submit name</button>

Preventing tainting the form

If you want to modify the form store without tainting any fields, you can update it with an extra option:

const { form } = superForm(data.form);

  ($form) => {
    $form.name = "New name";
    return $form;
  { taint: false }

The taint options are:

{ taint: boolean | 'untaint' | 'untaint-form' }

Which can be used to not only prevent tainting, but also untaint the modified field(s), or untainting the whole form.

Found a typo or an inconsistency? Make a quick correction here!