TanStack Form unterstützt Arrays als Werte in einem Formular, einschließlich Unterobjektwerten innerhalb eines Arrays.
Um ein Array zu verwenden, können Sie field.api.state.value für einen Array-Wert verwenden.
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<ng-container [tanstackField]="form" name="people" #people="field">
<div>
@for (_ of people.api.state.value; track $index) {
<!-- ... -->
}
</div>
</ng-container>
`,
})
export class AppComponent {
form = injectForm({
defaultValues: {
people: [] as Array<{ name: string; age: number }>,
},
onSubmit({ value }) {
alert(JSON.stringify(value))
},
})
}
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<ng-container [tanstackField]="form" name="people" #people="field">
<div>
@for (_ of people.api.state.value; track $index) {
<!-- ... -->
}
</div>
</ng-container>
`,
})
export class AppComponent {
form = injectForm({
defaultValues: {
people: [] as Array<{ name: string; age: number }>,
},
onSubmit({ value }) {
alert(JSON.stringify(value))
},
})
}
Dies generiert das zugeordnete JSX jedes Mal, wenn Sie pushValue auf field ausführen
<button (click)="people.api.pushValue(defaultPerson)" type="button">
Add person
</button>
<button (click)="people.api.pushValue(defaultPerson)" type="button">
Add person
</button>
Schließlich können Sie ein Unterfeld wie folgt verwenden
<ng-container
[tanstackField]="form"
[name]="getPeopleName($index)"
#person="field"
>
<div>
<label>
<div>Name for person {{ $index }}</div>
<input
[value]="person.api.state.value"
(input)="
person.api.handleChange($any($event).target.value)
"
/>
</label>
</div>
</ng-container>
<ng-container
[tanstackField]="form"
[name]="getPeopleName($index)"
#person="field"
>
<div>
<label>
<div>Name for person {{ $index }}</div>
<input
[value]="person.api.state.value"
(input)="
person.api.handleChange($any($event).target.value)
"
/>
</label>
</div>
</ng-container>
Wobei getPeopleName eine Methode in der Klasse ist, wie folgt:
export class AppComponent {
getPeopleName = (idx: number) => `people[${idx}].name` as const
// ...
}
export class AppComponent {
getPeopleName = (idx: number) => `people[${idx}].name` as const
// ...
}
Obwohl es bedauerlich ist, dass Sie eine Funktion verwenden müssen, um den Feldnamen zu erhalten, ist dies eine Anforderung für die Funktionsweise unserer strikten TypeScript-Typen.
Sehen Sie, wenn wir Folgendes tun würden:
angular-html<ng-container [tanstackField]="form" [name]="'people[' + $index + '].name'"></ng-container><ng-container [tanstackField]="form" [name]="'people[' + $index + '].name'"></ng-container>Würden wir auf ein TypeScript-Problem stoßen, bei dem "one" + "two" string ist und nicht der erforderliche "onetwo" Typ
Darüber hinaus unterstützt Angular zwar Template-Literale in der Vorlage, diese dürfen jedoch keine dynamische Interpolation enthalten, wie z. B. unser $index-Argument.
Es ist möglich, dass wir etwas übersehen haben! Wenn Ihnen eine bessere Lösung für dieses Problem einfällt, sprechen Sie uns in unseren GitHub-Diskussionen an.
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<form (submit)="handleSubmit($event)">
<div>
<ng-container [tanstackField]="form" name="people" #people="field">
<div>
@for (_ of people.api.state.value; track $index) {
<ng-container
[tanstackField]="form"
[name]="getPeopleName($index)"
#person="field"
>
<div>
<label>
<div>Name for person {{ $index }}</div>
<input
[value]="person.api.state.value"
(input)="
person.api.handleChange($any($event).target.value)
"
/>
</label>
</div>
</ng-container>
}
</div>
<button (click)="people.api.pushValue(defaultPerson)" type="button">
Add person
</button>
</ng-container>
</div>
<button type="submit" [disabled]="!canSubmit()">
{{ isSubmitting() ? '...' : 'Submit' }}
</button>
</form>
`,
})
export class AppComponent {
defaultPerson = { name: '', age: 0 }
form = injectForm({
defaultValues: {
people: [] as Array<{ name: string; age: number }>,
},
onSubmit({ value }) {
alert(JSON.stringify(value))
},
})
getPeopleName = (idx: number) => `people[${idx}].name` as const;
canSubmit = injectStore(this.form, (state) => state.canSubmit)
isSubmitting = injectStore(this.form, (state) => state.isSubmitting)
handleSubmit(event: SubmitEvent) {
event.preventDefault()
event.stopPropagation()
this.form.handleSubmit()
}
}
@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<form (submit)="handleSubmit($event)">
<div>
<ng-container [tanstackField]="form" name="people" #people="field">
<div>
@for (_ of people.api.state.value; track $index) {
<ng-container
[tanstackField]="form"
[name]="getPeopleName($index)"
#person="field"
>
<div>
<label>
<div>Name for person {{ $index }}</div>
<input
[value]="person.api.state.value"
(input)="
person.api.handleChange($any($event).target.value)
"
/>
</label>
</div>
</ng-container>
}
</div>
<button (click)="people.api.pushValue(defaultPerson)" type="button">
Add person
</button>
</ng-container>
</div>
<button type="submit" [disabled]="!canSubmit()">
{{ isSubmitting() ? '...' : 'Submit' }}
</button>
</form>
`,
})
export class AppComponent {
defaultPerson = { name: '', age: 0 }
form = injectForm({
defaultValues: {
people: [] as Array<{ name: string; age: number }>,
},
onSubmit({ value }) {
alert(JSON.stringify(value))
},
})
getPeopleName = (idx: number) => `people[${idx}].name` as const;
canSubmit = injectStore(this.form, (state) => state.canSubmit)
isSubmitting = injectStore(this.form, (state) => state.isSubmitting)
handleSubmit(event: SubmitEvent) {
event.preventDefault()
event.stopPropagation()
this.form.handleSubmit()
}
}
Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.