@tanstack/form-core
Advanced tools
Comparing version 0.20.0 to 0.20.1
@@ -87,3 +87,5 @@ import { Store } from '@tanstack/store'; | ||
insertValue: (index: number, value: TData extends any[] ? TData[number] : never) => void; | ||
removeValue: (index: number) => void; | ||
removeValue: (index: number, opts?: { | ||
touch: boolean; | ||
}) => Promise<void>; | ||
swapValues: (aIndex: number, bIndex: number) => void; | ||
@@ -90,0 +92,0 @@ getLinkedFields: (cause: ValidationCause) => FieldApi<any, any, any, any, any>[]; |
@@ -84,3 +84,5 @@ import { Store } from "@tanstack/store"; | ||
this.insertValue = (index, value) => this.form.insertFieldValue(this.name, index, value); | ||
this.removeValue = (index) => this.form.removeFieldValue(this.name, index); | ||
this.removeValue = async (index, opts2) => { | ||
await this.form.removeFieldValue(this.name, index, opts2); | ||
}; | ||
this.swapValues = (aIndex, bIndex) => this.form.swapFieldValues(this.name, aIndex, bIndex); | ||
@@ -87,0 +89,0 @@ this.getLinkedFields = (cause) => { |
@@ -119,5 +119,5 @@ import { Store } from '@tanstack/store'; | ||
touch?: boolean; | ||
}) => void; | ||
}) => Promise<void>; | ||
swapFieldValues: <TField extends DeepKeys<TFormData>>(field: TField, index1: number, index2: number) => void; | ||
moveFieldValues: <TField extends DeepKeys<TFormData>>(field: TField, index1: number, index2: number) => void; | ||
} |
@@ -362,3 +362,5 @@ import { Store } from "@tanstack/store"; | ||
}; | ||
this.removeFieldValue = (field, index, opts2) => { | ||
this.removeFieldValue = async (field, index, opts2) => { | ||
const fieldValue = this.getFieldValue(field); | ||
const lastIndex = Array.isArray(fieldValue) ? Math.max(fieldValue.length - 1, 0) : null; | ||
this.setFieldValue( | ||
@@ -373,2 +375,10 @@ field, | ||
); | ||
if (lastIndex !== null) { | ||
const start = `${field}[${lastIndex}]`; | ||
const fieldsToDelete = Object.keys(this.fieldInfo).filter( | ||
(f) => f.startsWith(start) | ||
); | ||
fieldsToDelete.forEach((f) => this.deleteField(f)); | ||
} | ||
await this.validateAllFields("change"); | ||
}; | ||
@@ -375,0 +385,0 @@ this.swapFieldValues = (field, index1, index2) => { |
{ | ||
"name": "@tanstack/form-core", | ||
"version": "0.20.0", | ||
"version": "0.20.1", | ||
"description": "Powerful, type-safe, framework agnostic forms.", | ||
@@ -5,0 +5,0 @@ "author": "tannerlinsley", |
@@ -480,3 +480,5 @@ import { Store } from '@tanstack/store' | ||
removeValue = (index: number) => this.form.removeFieldValue(this.name, index) | ||
removeValue = async (index: number, opts?: { touch: boolean }) => { | ||
await this.form.removeFieldValue(this.name, index, opts) | ||
} | ||
@@ -483,0 +485,0 @@ swapValues = (aIndex: number, bIndex: number) => |
@@ -718,3 +718,3 @@ import { Store } from '@tanstack/store' | ||
removeFieldValue = <TField extends DeepKeys<TFormData>>( | ||
removeFieldValue = async <TField extends DeepKeys<TFormData>>( | ||
field: TField, | ||
@@ -724,2 +724,8 @@ index: number, | ||
) => { | ||
const fieldValue = this.getFieldValue(field) | ||
const lastIndex = Array.isArray(fieldValue) | ||
? Math.max(fieldValue.length - 1, 0) | ||
: null | ||
this.setFieldValue( | ||
@@ -734,2 +740,14 @@ field, | ||
) | ||
if (lastIndex !== null) { | ||
const start = `${field}[${lastIndex}]` | ||
const fieldsToDelete = Object.keys(this.fieldInfo).filter((f) => | ||
f.startsWith(start), | ||
) | ||
// Cleanup the last fields | ||
fieldsToDelete.forEach((f) => this.deleteField(f as TField)) | ||
} | ||
await this.validateAllFields('change') | ||
} | ||
@@ -736,0 +754,0 @@ |
@@ -144,2 +144,113 @@ import { describe, expect, it, vi } from 'vitest' | ||
it('should remove a subfield from an array field correctly', async () => { | ||
const form = new FormApi({ | ||
defaultValues: { | ||
people: [] as Array<{ name: string }>, | ||
}, | ||
}) | ||
const field = new FieldApi({ | ||
form, | ||
name: 'people', | ||
}) | ||
const subFieldValidators = { | ||
onChange: ({ value }: { value: string }) => | ||
value.length === 0 ? 'Required' : null, | ||
} | ||
const subField1 = new FieldApi({ | ||
form: field.form, | ||
name: 'people[0].name', | ||
defaultValue: '', | ||
validators: subFieldValidators, | ||
}) | ||
const subField2 = new FieldApi({ | ||
form: field.form, | ||
name: 'people[1].name', | ||
defaultValue: 'hello', | ||
validators: subFieldValidators, | ||
}) | ||
const subField3 = new FieldApi({ | ||
form: field.form, | ||
name: 'people[2].name', | ||
defaultValue: '', | ||
validators: subFieldValidators, | ||
}) | ||
const subField4 = new FieldApi({ | ||
form: field.form, | ||
name: 'people[3].name', | ||
defaultValue: 'world', | ||
validators: subFieldValidators, | ||
}) | ||
;[form, field, subField1, subField2, subField3, subField4].forEach((f) => | ||
f.mount(), | ||
) | ||
await form.handleSubmit() | ||
expect(subField1.state.meta.errorMap.onChange).toStrictEqual('Required') | ||
expect(subField2.state.meta.errorMap.onChange).toStrictEqual(undefined) | ||
expect(subField3.state.meta.errorMap.onChange).toStrictEqual('Required') | ||
expect(subField4.state.meta.errorMap.onChange).toStrictEqual(undefined) | ||
await field.removeValue(0 /* subField1 */, { touch: true }) | ||
expect(subField1.state.value).toBe('hello') | ||
expect(subField1.state.meta.errorMap.onChange).toStrictEqual(undefined) | ||
expect(subField2.state.value).toBe('') | ||
expect(subField2.state.meta.errorMap.onChange).toStrictEqual('Required') | ||
expect(subField3.state.value).toBe('world') | ||
expect(subField3.state.meta.errorMap.onChange).toStrictEqual(undefined) | ||
expect(form.getFieldInfo('people[0].name').instance?.state.value).toBe( | ||
'hello', | ||
) | ||
expect(form.getFieldInfo('people[1].name').instance?.state.value).toBe('') | ||
expect(form.getFieldInfo('people[2].name').instance?.state.value).toBe( | ||
'world', | ||
) | ||
}) | ||
it('should remove remove the last subfield from an array field correctly', async () => { | ||
const form = new FormApi({ | ||
defaultValues: { | ||
people: [] as Array<{ name: string }>, | ||
}, | ||
}) | ||
const field = new FieldApi({ | ||
form, | ||
name: 'people', | ||
}) | ||
const subFieldValidators = { | ||
onChange: ({ value }: { value: string }) => | ||
value.length === 0 ? 'Required' : null, | ||
} | ||
const subField1 = new FieldApi({ | ||
form: field.form, | ||
name: 'people[0].name', | ||
defaultValue: '', | ||
validators: subFieldValidators, | ||
}) | ||
;[form, field, subField1].forEach((f) => f.mount()) | ||
await form.handleSubmit() | ||
expect(subField1.state.meta.errorMap.onChange).toStrictEqual('Required') | ||
await field.removeValue(0 /* subField1 */, { touch: true }) | ||
expect(subField1.state.value).toBe(undefined) | ||
expect(subField1.state.meta.errorMap.onChange).toStrictEqual(undefined) | ||
expect(form.state.canSubmit).toBe(true) | ||
}) | ||
it('should swap a value from an array value correctly', () => { | ||
@@ -146,0 +257,0 @@ const form = new FormApi({ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
388309
6535