Skip to content

Commit 4abbc8a

Browse files
authored
fix(form-core): prevent onBlur and onChange form listeners from canceling each other (#1593)
1 parent 0d949d6 commit 4abbc8a

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

packages/form-core/src/FieldApi.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,11 +1770,11 @@ export class FieldApi<
17701770
private triggerOnChangeListener() {
17711771
const formDebounceMs = this.form.options.listeners?.onChangeDebounceMs
17721772
if (formDebounceMs && formDebounceMs > 0) {
1773-
if (this.timeoutIds.formListeners.blur) {
1774-
clearTimeout(this.timeoutIds.formListeners.blur)
1773+
if (this.timeoutIds.formListeners.change) {
1774+
clearTimeout(this.timeoutIds.formListeners.change)
17751775
}
17761776

1777-
this.timeoutIds.formListeners.blur = setTimeout(() => {
1777+
this.timeoutIds.formListeners.change = setTimeout(() => {
17781778
this.form.options.listeners?.onChange?.({
17791779
formApi: this.form,
17801780
fieldApi: this,

packages/form-core/tests/FormApi.spec.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2192,6 +2192,45 @@ describe('form api', () => {
21922192
expect(onBlurMock).toHaveBeenCalledTimes(1)
21932193
})
21942194

2195+
it('should run both onBlur and onChange listeners when onBlurDebounceMs and onChangeDebounceMs are provided', async () => {
2196+
vi.useFakeTimers()
2197+
const onBlurMock = vi.fn()
2198+
const onChangeMock = vi.fn()
2199+
2200+
const form = new FormApi({
2201+
defaultValues: {
2202+
name: 'test',
2203+
age: 0,
2204+
},
2205+
listeners: {
2206+
onBlur: onBlurMock,
2207+
onBlurDebounceMs: 500,
2208+
onChange: onChangeMock,
2209+
onChangeDebounceMs: 500,
2210+
},
2211+
})
2212+
form.mount()
2213+
2214+
const field = new FieldApi({
2215+
form,
2216+
name: 'name',
2217+
})
2218+
field.mount()
2219+
field.handleBlur()
2220+
field.handleChange('test')
2221+
2222+
await vi.advanceTimersByTimeAsync(500)
2223+
expect(onBlurMock).toHaveBeenCalledTimes(1)
2224+
expect(onChangeMock).toHaveBeenCalledTimes(1)
2225+
2226+
field.handleChange('test2')
2227+
field.handleBlur()
2228+
2229+
await vi.advanceTimersByTimeAsync(500)
2230+
expect(onBlurMock).toHaveBeenCalledTimes(2)
2231+
expect(onChangeMock).toHaveBeenCalledTimes(2)
2232+
})
2233+
21952234
it('should run the field listener onSubmit', async () => {
21962235
const form = new FormApi({
21972236
defaultValues: {

0 commit comments

Comments
 (0)