Dynamische Validierung

In vielen Fällen möchten Sie die Validierungsregeln basierend auf dem Zustand des Formulars oder anderen Bedingungen ändern. Das beliebteste Beispiel dafür ist, wenn Sie ein Feld anders validieren möchten, je nachdem, ob der Benutzer das Formular zum ersten Mal übermittelt hat oder nicht.

Wir unterstützen dies durch unsere onDynamic Validierungsfunktion.

ts
import { LitElement, html } from 'lit'
import { customElement } from 'lit/decorators.js'
import { TanStackFormController, revalidateLogic } from '@tanstack/lit-form'

@customElement('my-form')
export class MyForm extends LitElement {
  #form = new TanStackFormController(this, {
    defaultValues: {
      firstName: '',
      lastName: '',
    },
    // If this is omitted, onDynamic will not be called
    validationLogic: revalidateLogic(),
    validators: {
      onDynamic: ({ value }) => {
        if (!value.firstName) {
          return { firstName: 'A first name is required' }
        }
        return undefined
      },
    },
  })

  render() {
    return html`<!-- form content -->`
  }
}
import { LitElement, html } from 'lit'
import { customElement } from 'lit/decorators.js'
import { TanStackFormController, revalidateLogic } from '@tanstack/lit-form'

@customElement('my-form')
export class MyForm extends LitElement {
  #form = new TanStackFormController(this, {
    defaultValues: {
      firstName: '',
      lastName: '',
    },
    // If this is omitted, onDynamic will not be called
    validationLogic: revalidateLogic(),
    validators: {
      onDynamic: ({ value }) => {
        if (!value.firstName) {
          return { firstName: 'A first name is required' }
        }
        return undefined
      },
    },
  })

  render() {
    return html`<!-- form content -->`
  }
}

Standardmäßig wird onDynamic nicht aufgerufen. Sie müssen also revalidateLogic() an die Option validationLogic von useForm übergeben.

Revalidierungsoptionen

revalidateLogic ermöglicht es Ihnen anzugeben, wann die Validierung ausgeführt werden soll und die Validierungsregeln dynamisch basierend auf dem aktuellen Übermittlungsstatus des Formulars zu ändern.

Es nimmt zwei Argumente entgegen

  • mode: Der Validierungsmodus vor der ersten Formularübermittlung. Dies kann einer der folgenden sein:

    • change: Validieren bei jeder Änderung.
    • blur: Validieren beim Verlassen des Feldes (Blur).
    • submit: Validieren bei Übermittlung. (Standard)
  • modeAfterSubmission: Der Validierungsmodus, nachdem das Formular übermittelt wurde. Dies kann einer der folgenden sein:

    • change: Validieren bei jeder Änderung. (Standard)
    • blur: Validieren beim Verlassen des Feldes (Blur).
    • submit: Validieren bei Übermittlung.

Sie können beispielsweise das Folgende verwenden, um nach der ersten Übermittlung beim Verlassen des Feldes neu zu validieren.

ts
@customElement('my-form')
export class MyForm extends LitElement {
  #form = new TanStackFormController(this, {
    // ...
    validationLogic: revalidateLogic({
      mode: 'submit',
      modeAfterSubmission: 'blur',
    }),
    // ...
  })
}
@customElement('my-form')
export class MyForm extends LitElement {
  #form = new TanStackFormController(this, {
    // ...
    validationLogic: revalidateLogic({
      mode: 'submit',
      modeAfterSubmission: 'blur',
    }),
    // ...
  })
}

Zugriff auf Fehler

Genauso wie Sie Fehler aus einer onChange oder onBlur Validierung abrufen können, können Sie die Fehler aus der onDynamic Validierungsfunktion über das Objekt form.api.state.errorMap abrufen.

ts
import { LitElement, html } from 'lit'
import { customElement } from 'lit/decorators.js'
import { TanStackFormController, revalidateLogic } from '@tanstack/lit-form'

@customElement('my-form')
export class MyForm extends LitElement {
  #form = new TanStackFormController(this, {
    // ...
    validationLogic: revalidateLogic(),
    validators: {
      onDynamic: ({ value }) => {
        if (!value.firstName) {
          return { firstName: 'A first name is required' }
        }
        return undefined
      },
    },
  })

  render() {
    return html`<p>${this.#form.api.state.errorMap.onDynamic?.firstName}</p>`
  }
}
import { LitElement, html } from 'lit'
import { customElement } from 'lit/decorators.js'
import { TanStackFormController, revalidateLogic } from '@tanstack/lit-form'

@customElement('my-form')
export class MyForm extends LitElement {
  #form = new TanStackFormController(this, {
    // ...
    validationLogic: revalidateLogic(),
    validators: {
      onDynamic: ({ value }) => {
        if (!value.firstName) {
          return { firstName: 'A first name is required' }
        }
        return undefined
      },
    },
  })

  render() {
    return html`<p>${this.#form.api.state.errorMap.onDynamic?.firstName}</p>`
  }
}

Verwendung mit anderer Validierungslogik

Sie können die onDynamic Validierung neben anderer Validierungslogik verwenden, wie z. B. onChange oder onBlur.

ts
import { LitElement, html } from 'lit'
import { customElement } from 'lit/decorators.js'
import { TanStackFormController, revalidateLogic } from '@tanstack/lit-form'

@customElement('my-form')
export class MyForm extends LitElement {
  #form = new TanStackFormController(this, {
    defaultValues: {
      firstName: '',
      lastName: '',
    },
    validationLogic: revalidateLogic(),
    validators: {
      onChange: ({ value }) => {
        if (!value.firstName) {
          return { firstName: 'A first name is required' }
        }
        return undefined
      },
      onDynamic: ({ value }) => {
        if (!value.lastName) {
          return { lastName: 'A last name is required' }
        }
        return undefined
      },
    },
  })

  render() {
    return html`
      <div>
        <p>${this.#form.api.state.errorMap.onChange?.firstName}</p>
        <p>${this.#form.api.state.errorMap.onDynamic?.lastName}</p>
      </div>
    `
  }
}
import { LitElement, html } from 'lit'
import { customElement } from 'lit/decorators.js'
import { TanStackFormController, revalidateLogic } from '@tanstack/lit-form'

@customElement('my-form')
export class MyForm extends LitElement {
  #form = new TanStackFormController(this, {
    defaultValues: {
      firstName: '',
      lastName: '',
    },
    validationLogic: revalidateLogic(),
    validators: {
      onChange: ({ value }) => {
        if (!value.firstName) {
          return { firstName: 'A first name is required' }
        }
        return undefined
      },
      onDynamic: ({ value }) => {
        if (!value.lastName) {
          return { lastName: 'A last name is required' }
        }
        return undefined
      },
    },
  })

  render() {
    return html`
      <div>
        <p>${this.#form.api.state.errorMap.onChange?.firstName}</p>
        <p>${this.#form.api.state.errorMap.onDynamic?.lastName}</p>
      </div>
    `
  }
}

Verwendung mit Feldern

Sie können die onDynamic Validierung auch mit Feldern verwenden, genau wie Sie es mit anderer Validierungslogik tun würden.

ts
import { LitElement, html } from 'lit'
import { customElement } from 'lit/decorators.js'
import { TanStackFormController, revalidateLogic } from '@tanstack/lit-form'

@customElement('my-form')
export class MyForm extends LitElement {
  #form = new TanStackFormController(this, {
    defaultValues: {
      name: '',
      age: 0,
    },
    validationLogic: revalidateLogic(),
    onSubmit({ value }) {
      alert(JSON.stringify(value))
    },
  })

  render() {
    return html`
      <form
        @submit=${(e: Event) => {
          e.preventDefault()
          e.stopPropagation()
          this.#form.api.handleSubmit()
        }}
      >
        ${this.#form.field(
          {
            name: 'age',
            validators: {
              onDynamic: ({ value }) =>
                value > 18 ? undefined : 'Age must be greater than 18',
            },
          },
          (field) => html`
            <div>
              <input
                type="number"
                .value=${field.state.value}
                @input=${(e: Event) => {
                  const target = e.target as HTMLInputElement
                  field.handleChange(target.valueAsNumber)
                }}
                @blur=${() => field.handleBlur()}
              />
              <p style="color: red;">${field.state.meta.errorMap.onDynamic}</p>
            </div>
          `,
        )}
        <button type="submit">Submit</button>
      </form>
    `
  }
}
import { LitElement, html } from 'lit'
import { customElement } from 'lit/decorators.js'
import { TanStackFormController, revalidateLogic } from '@tanstack/lit-form'

@customElement('my-form')
export class MyForm extends LitElement {
  #form = new TanStackFormController(this, {
    defaultValues: {
      name: '',
      age: 0,
    },
    validationLogic: revalidateLogic(),
    onSubmit({ value }) {
      alert(JSON.stringify(value))
    },
  })

  render() {
    return html`
      <form
        @submit=${(e: Event) => {
          e.preventDefault()
          e.stopPropagation()
          this.#form.api.handleSubmit()
        }}
      >
        ${this.#form.field(
          {
            name: 'age',
            validators: {
              onDynamic: ({ value }) =>
                value > 18 ? undefined : 'Age must be greater than 18',
            },
          },
          (field) => html`
            <div>
              <input
                type="number"
                .value=${field.state.value}
                @input=${(e: Event) => {
                  const target = e.target as HTMLInputElement
                  field.handleChange(target.valueAsNumber)
                }}
                @blur=${() => field.handleBlur()}
              />
              <p style="color: red;">${field.state.meta.errorMap.onDynamic}</p>
            </div>
          `,
        )}
        <button type="submit">Submit</button>
      </form>
    `
  }
}

Asynchrone Validierung

Asynchrone Validierung kann auch mit onDynamic verwendet werden, genau wie mit anderer Validierungslogik. Sie können die asynchrone Validierung sogar verzögern (debounce), um übermäßige Aufrufe zu vermeiden.

ts
import { LitElement } from 'lit'
import { customElement } from 'lit/decorators.js'
import { TanStackFormController, revalidateLogic } from '@tanstack/lit-form'

@customElement('my-form')
export class MyForm extends LitElement {
  #form = new TanStackFormController(this, {
    defaultValues: {
      username: '',
    },
    validationLogic: revalidateLogic(),
    validators: {
      onDynamicAsyncDebounceMs: 500, // Debounce the async validation by 500ms
      onDynamicAsync: async ({ value }) => {
        if (!value.username) {
          return { username: 'Username is required' }
        }
        // Simulate an async validation
        const isValid = await validateUsername(value.username)
        return isValid ? undefined : { username: 'Username is already taken' }
      },
    },
  })
}
import { LitElement } from 'lit'
import { customElement } from 'lit/decorators.js'
import { TanStackFormController, revalidateLogic } from '@tanstack/lit-form'

@customElement('my-form')
export class MyForm extends LitElement {
  #form = new TanStackFormController(this, {
    defaultValues: {
      username: '',
    },
    validationLogic: revalidateLogic(),
    validators: {
      onDynamicAsyncDebounceMs: 500, // Debounce the async validation by 500ms
      onDynamicAsync: async ({ value }) => {
        if (!value.username) {
          return { username: 'Username is required' }
        }
        // Simulate an async validation
        const isValid = await validateUsername(value.username)
        return isValid ? undefined : { username: 'Username is already taken' }
      },
    },
  })
}

Standard-Schema-Validierung

Sie können auch Standard-Schema-Validierungsbibliotheken wie Valibot oder Zod mit der onDynamic Validierung verwenden. Dies ermöglicht es Ihnen, komplexe Validierungsregeln zu definieren, die sich dynamisch basierend auf dem Formularzustand ändern können.

ts
import { LitElement } from 'lit'
import { customElement } from 'lit/decorators.js'
import { TanStackFormController, revalidateLogic } from '@tanstack/lit-form'
import { z } from 'zod'

const schema = z.object({
  firstName: z.string().min(1, 'A first name is required'),
  lastName: z.string().min(1, 'A last name is required'),
})

@customElement('my-form')
export class MyForm extends LitElement {
  #form = new TanStackFormController(this, {
    defaultValues: {
      firstName: '',
      lastName: '',
    },
    validationLogic: revalidateLogic(),
    validators: {
      onDynamic: schema,
    },
  })
}
import { LitElement } from 'lit'
import { customElement } from 'lit/decorators.js'
import { TanStackFormController, revalidateLogic } from '@tanstack/lit-form'
import { z } from 'zod'

const schema = z.object({
  firstName: z.string().min(1, 'A first name is required'),
  lastName: z.string().min(1, 'A last name is required'),
})

@customElement('my-form')
export class MyForm extends LitElement {
  #form = new TanStackFormController(this, {
    defaultValues: {
      firstName: '',
      lastName: '',
    },
    validationLogic: revalidateLogic(),
    validators: {
      onDynamic: schema,
    },
  })
}
Unsere Partner
Code Rabbit
Bytes abonnieren

Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.

Bytes

Kein Spam. Jederzeit kündbar.

Bytes abonnieren

Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.

Bytes

Kein Spam. Jederzeit kündbar.