Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: insert value behaviour #697

Merged
merged 4 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 6 additions & 1 deletion docs/reference/fieldApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,12 @@ A class representing the API for managing a form field.
insertValue(index: number, value: TData): void
```

- Inserts a value at the specified index.
- Inserts a value at the specified index, shifting the subsequent values to the right.

- ```tsx
replaceValue(index: number, value: TData): void
```
- Replaces a value at the specified index.

- ```tsx
removeValue(index: number): Promise<void>
Expand Down
6 changes: 5 additions & 1 deletion docs/reference/formApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,11 @@ A class representing the Form API. It handles the logic and interactions with th
- ```tsx
insertFieldValue<TField extends DeepKeys<TFormData>>(field: TField, index: number, value: DeepValue<TFormData, TField>, opts?: { touch?: boolean })
```
- Inserts a value into an array field at the specified index.
- Inserts a value into an array field at the specified index, shifting the subsequent values to the right.
- ```tsx
replaceFieldValue<TField extends DeepKeys<TFormData>>(field: TField, index: number, value: DeepValue<TFormData, TField>, opts?: { touch?: boolean })
```
- Replaces a value into an array field at the specified index.
- ```tsx
removeFieldValue<TField extends DeepKeys<TFormData>>(field: TField, index: number, opts?: { touch?: boolean })
```
Expand Down
5 changes: 5 additions & 0 deletions packages/form-core/src/FieldApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,11 @@ export class FieldApi<
value: TData extends any[] ? TData[number] : never,
) => this.form.insertFieldValue(this.name, index, value as any)

replaceValue = (
index: number,
value: TData extends any[] ? TData[number] : never,
) => this.form.replaceFieldValue(this.name, index, value as any)

removeValue = (index: number, opts?: { touch: boolean }) =>
this.form.removeFieldValue(this.name, index, opts)

Expand Down
24 changes: 24 additions & 0 deletions packages/form-core/src/FormApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,30 @@ export class FormApi<
? DeepValue<TFormData, TField>[number]
: never,
opts?: { touch?: boolean },
) => {
this.setFieldValue(
field,
(prev) => {
return [
...(prev as DeepValue<TFormData, TField>[]).slice(0, index),
value,
...(prev as DeepValue<TFormData, TField>[]).slice(index),
] as any
},
opts,
)

// Validate the whole array + all fields that have shifted
await this.validateField(field, 'change')
}

replaceFieldValue = async <TField extends DeepKeys<TFormData>>(
field: TField,
index: number,
value: DeepValue<TFormData, TField> extends any[]
? DeepValue<TFormData, TField>[number]
: never,
opts?: { touch?: boolean },
) => {
this.setFieldValue(
field,
Expand Down
36 changes: 35 additions & 1 deletion packages/form-core/src/tests/FieldApi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,41 @@ describe('field api', () => {

field.insertValue(1, 'other')

expect(field.getValue()).toStrictEqual(['one', 'other'])
expect(field.getValue()).toStrictEqual(['one', 'other', 'two'])
})

it('should replace a value into an array correctly', () => {
const form = new FormApi({
defaultValues: {
names: ['one', 'two', 'three'],
},
})

const field = new FieldApi({
form,
name: 'names',
})

field.replaceValue(1, 'other')

expect(field.getValue()).toStrictEqual(['one', 'other', 'three'])
})

it('should do nothing when replacing a value into an array at an index that does not exist', () => {
const form = new FormApi({
defaultValues: {
names: ['one', 'two', 'three'],
},
})

const field = new FieldApi({
form,
name: 'names',
})

field.replaceValue(10, 'other')

expect(field.getValue()).toStrictEqual(['one', 'two', 'three'])
})

it('should run onChange validation when inserting an array fields value', () => {
Expand Down
65 changes: 64 additions & 1 deletion packages/form-core/src/tests/FormApi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,23 @@ describe('form api', () => {
expect(form.getFieldValue('names')).toStrictEqual(['test', 'other'])
})

it("should insert an array field's value as first element", () => {
const form = new FormApi({
defaultValues: {
names: ['one', 'two', 'three'],
},
})
form.mount()
form.insertFieldValue('names', 0, 'other')

expect(form.getFieldValue('names')).toStrictEqual([
'other',
'one',
'two',
'three',
])
})

it("should run onChange validation when pushing an array field's value", () => {
const form = new FormApi({
defaultValues: {
Expand Down Expand Up @@ -352,9 +369,55 @@ describe('form api', () => {
form.mount()
form.insertFieldValue('names', 1, 'other')

expect(form.getFieldValue('names')).toStrictEqual([
'one',
'other',
'two',
'three',
])
})

it("should insert an array field's value at the end if the index is higher than the length", () => {
const form = new FormApi({
defaultValues: {
names: ['one', 'two', 'three'],
},
})
form.mount()
form.insertFieldValue('names', 10, 'other')

expect(form.getFieldValue('names')).toStrictEqual([
'one',
'two',
'three',
'other',
])
})

it("should replace an array field's value", () => {
const form = new FormApi({
defaultValues: {
names: ['one', 'two', 'three'],
},
})
form.mount()
form.replaceFieldValue('names', 1, 'other')

expect(form.getFieldValue('names')).toStrictEqual(['one', 'other', 'three'])
})

it("should do nothing when replacing an array field's value with an index that doesn't exist", () => {
const form = new FormApi({
defaultValues: {
names: ['one', 'two', 'three'],
},
})
form.mount()
form.replaceFieldValue('names', 10, 'other')

expect(form.getFieldValue('names')).toStrictEqual(['one', 'two', 'three'])
})

it("should run onChange validation when inserting an array field's value", () => {
const form = new FormApi({
defaultValues: {
Expand Down Expand Up @@ -400,7 +463,7 @@ describe('form api', () => {

expect(field1.state.meta.errors).toStrictEqual([])

await form.insertFieldValue('names', 0, { first: 'other' })
await form.replaceFieldValue('names', 0, { first: 'other' })

expect(field1.state.meta.errors).toStrictEqual(['Invalid value'])
})
Expand Down