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.
import { Component } from '@angular/core'
import { TanStackField, injectForm, revalidateLogic } from '@tanstack/angular-form'
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<!-- Your form template here -->
`,
})
export class AppComponent {
form = injectForm({
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
},
},
})
}
import { Component } from '@angular/core'
import { TanStackField, injectForm, revalidateLogic } from '@tanstack/angular-form'
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<!-- Your form template here -->
`,
})
export class AppComponent {
form = injectForm({
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
},
},
})
}
Standardmäßig wird onDynamic nicht aufgerufen, daher müssen Sie revalidateLogic() an die Option validationLogic von injectForm übergeben.
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:
modeAfterSubmission: Der Validierungsmodus, nachdem das Formular übermittelt wurde. Dies kann einer der folgenden sein:
Sie können beispielsweise das Folgende verwenden, um nach der ersten Übermittlung beim Verlassen des Feldes neu zu validieren.
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<!-- Your form template here -->
`,
})
export class AppComponent {
form = injectForm({
// ...
validationLogic: revalidateLogic({
mode: 'submit',
modeAfterSubmission: 'blur',
}),
// ...
})
}
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<!-- Your form template here -->
`,
})
export class AppComponent {
form = injectForm({
// ...
validationLogic: revalidateLogic({
mode: 'submit',
modeAfterSubmission: 'blur',
}),
// ...
})
}
So wie Sie auf Fehler von einer onChange oder onBlur Validierung zugreifen können, können Sie mit dem Fehler-Map des Formulars über injectStore auf die Fehler der onDynamic Validierungsfunktion zugreifen.
import { Component } from '@angular/core'
import { TanStackField, injectForm, injectStore, revalidateLogic } from '@tanstack/angular-form'
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<p>{{ formErrorMap().onDynamic?.firstName }}</p>
`,
})
export class AppComponent {
form = injectForm({
// ...
validationLogic: revalidateLogic(),
validators: {
onDynamic: ({ value }) => {
if (!value.firstName) {
return { firstName: 'A first name is required' }
}
return undefined
},
},
})
formErrorMap = injectStore(this.form, (state) => state.errorMap)
}
import { Component } from '@angular/core'
import { TanStackField, injectForm, injectStore, revalidateLogic } from '@tanstack/angular-form'
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<p>{{ formErrorMap().onDynamic?.firstName }}</p>
`,
})
export class AppComponent {
form = injectForm({
// ...
validationLogic: revalidateLogic(),
validators: {
onDynamic: ({ value }) => {
if (!value.firstName) {
return { firstName: 'A first name is required' }
}
return undefined
},
},
})
formErrorMap = injectStore(this.form, (state) => state.errorMap)
}
Sie können die onDynamic Validierung neben anderer Validierungslogik verwenden, wie z. B. onChange oder onBlur.
import { Component } from '@angular/core'
import { TanStackField, injectForm, injectStore, revalidateLogic } from '@tanstack/angular-form'
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<div>
<p>{{ formErrorMap().onChange?.firstName }}</p>
<p>{{ formErrorMap().onDynamic?.lastName }}</p>
</div>
`,
})
export class AppComponent {
form = injectForm({
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
},
},
})
formErrorMap = injectStore(this.form, (state) => state.errorMap)
}
import { Component } from '@angular/core'
import { TanStackField, injectForm, injectStore, revalidateLogic } from '@tanstack/angular-form'
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<div>
<p>{{ formErrorMap().onChange?.firstName }}</p>
<p>{{ formErrorMap().onDynamic?.lastName }}</p>
</div>
`,
})
export class AppComponent {
form = injectForm({
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
},
},
})
formErrorMap = injectStore(this.form, (state) => state.errorMap)
}
Sie können die onDynamic Validierung auch mit Feldern verwenden, genau wie Sie es mit anderer Validierungslogik tun würden.
import { Component } from '@angular/core'
import { TanStackField, injectForm, revalidateLogic } from '@tanstack/angular-form'
import type { FieldValidateFn } from '@tanstack/angular-form'
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<form (submit)="handleSubmit($event)">
<ng-container
[tanstackField]="form"
name="age"
[validators]="{
onDynamic: ageValidator
}"
#age="field"
>
<input
type="number"
[value]="age.api.state.value"
(blur)="age.api.handleBlur()"
(input)="age.api.handleChange($any($event).target.valueAsNumber)"
/>
@if (age.api.state.meta.errorMap.onDynamic) {
<p style="color: red">
{{ age.api.state.meta.errorMap.onDynamic }}
</p>
}
</ng-container>
<button type="submit">Submit</button>
</form>
`,
})
export class AppComponent {
ageValidator: FieldValidateFn<any, any, any, any, number> = ({ value }) =>
value > 18 ? undefined : 'Age must be greater than 18'
form = injectForm({
defaultValues: {
name: '',
age: 0,
},
validationLogic: revalidateLogic(),
onSubmit({ value }) {
alert(JSON.stringify(value))
},
})
handleSubmit(event: SubmitEvent) {
event.preventDefault()
event.stopPropagation()
this.form.handleSubmit()
}
}
import { Component } from '@angular/core'
import { TanStackField, injectForm, revalidateLogic } from '@tanstack/angular-form'
import type { FieldValidateFn } from '@tanstack/angular-form'
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<form (submit)="handleSubmit($event)">
<ng-container
[tanstackField]="form"
name="age"
[validators]="{
onDynamic: ageValidator
}"
#age="field"
>
<input
type="number"
[value]="age.api.state.value"
(blur)="age.api.handleBlur()"
(input)="age.api.handleChange($any($event).target.valueAsNumber)"
/>
@if (age.api.state.meta.errorMap.onDynamic) {
<p style="color: red">
{{ age.api.state.meta.errorMap.onDynamic }}
</p>
}
</ng-container>
<button type="submit">Submit</button>
</form>
`,
})
export class AppComponent {
ageValidator: FieldValidateFn<any, any, any, any, number> = ({ value }) =>
value > 18 ? undefined : 'Age must be greater than 18'
form = injectForm({
defaultValues: {
name: '',
age: 0,
},
validationLogic: revalidateLogic(),
onSubmit({ value }) {
alert(JSON.stringify(value))
},
})
handleSubmit(event: SubmitEvent) {
event.preventDefault()
event.stopPropagation()
this.form.handleSubmit()
}
}
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.
import { Component } from '@angular/core'
import { TanStackField, injectForm, revalidateLogic } from '@tanstack/angular-form'
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<!-- Your form template here -->
`,
})
export class AppComponent {
form = injectForm({
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 { Component } from '@angular/core'
import { TanStackField, injectForm, revalidateLogic } from '@tanstack/angular-form'
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<!-- Your form template here -->
`,
})
export class AppComponent {
form = injectForm({
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' }
},
},
})
}
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.
import { Component } from '@angular/core'
import { TanStackField, injectForm, revalidateLogic } from '@tanstack/angular-form'
import { z } from 'zod'
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<!-- Your form template here -->
`,
})
export class AppComponent {
schema = z.object({
firstName: z.string().min(1, 'A first name is required'),
lastName: z.string().min(1, 'A last name is required'),
})
form = injectForm({
defaultValues: {
firstName: '',
lastName: '',
},
validationLogic: revalidateLogic(),
validators: {
onDynamic: this.schema,
},
})
}
import { Component } from '@angular/core'
import { TanStackField, injectForm, revalidateLogic } from '@tanstack/angular-form'
import { z } from 'zod'
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<!-- Your form template here -->
`,
})
export class AppComponent {
schema = z.object({
firstName: z.string().min(1, 'A first name is required'),
lastName: z.string().min(1, 'A last name is required'),
})
form = injectForm({
defaultValues: {
firstName: '',
lastName: '',
},
validationLogic: revalidateLogic(),
validators: {
onDynamic: this.schema,
},
})
}
Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.