Skip to content

Commit 47b8ff7

Browse files
authored
feat: add isBlurred field state (#938)
closes #939
1 parent 94d7ff7 commit 47b8ff7

File tree

4 files changed

+45
-1
lines changed

4 files changed

+45
-1
lines changed

packages/form-core/src/FieldApi.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,10 @@ export type FieldMeta = {
335335
* A flag indicating whether the field has been touched.
336336
*/
337337
isTouched: boolean
338+
/**
339+
* A flag indicating whether the field has been blurred.
340+
*/
341+
isBlurred: boolean
338342
/**
339343
* A flag that is `true` if the field's value has not been modified by the user. Opposite of `isDirty`.
340344
*/
@@ -456,6 +460,7 @@ export class FieldApi<
456460
meta: this._getMeta() ?? {
457461
isValidating: false,
458462
isTouched: false,
463+
isBlurred: false,
459464
isDirty: false,
460465
isPristine: true,
461466
errors: [],
@@ -625,6 +630,7 @@ export class FieldApi<
625630
({
626631
isValidating: false,
627632
isTouched: false,
633+
isBlurred: false,
628634
isDirty: false,
629635
isPristine: true,
630636
errors: [],
@@ -1001,6 +1007,9 @@ export class FieldApi<
10011007
this.setMeta((prev) => ({ ...prev, isTouched: true }))
10021008
this.validate('change')
10031009
}
1010+
if (!this.state.meta.isBlurred) {
1011+
this.setMeta((prev) => ({ ...prev, isBlurred: true }))
1012+
}
10041013
this.validate('blur')
10051014
}
10061015

packages/form-core/src/FormApi.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ export type FormState<TFormData> = {
259259
* A boolean indicating if any of the form fields have been touched.
260260
*/
261261
isTouched: boolean
262+
/**
263+
* A boolean indicating if any of the form fields have been blurred.
264+
*/
265+
isBlurred: boolean
262266
/**
263267
* A boolean indicating if any of the form's fields' values have been modified by the user. `True` if the user have modified at least one of the fields. Opposite of `isPristine`.
264268
*/
@@ -305,6 +309,7 @@ function getDefaultFormState<TFormData>(
305309
isSubmitted: defaultState.isSubmitted ?? false,
306310
isSubmitting: defaultState.isSubmitting ?? false,
307311
isTouched: defaultState.isTouched ?? false,
312+
isBlurred: defaultState.isBlurred ?? false,
308313
isPristine: defaultState.isPristine ?? true,
309314
isDirty: defaultState.isDirty ?? false,
310315
isValid: defaultState.isValid ?? false,
@@ -388,6 +393,7 @@ export class FormApi<
388393
)
389394

390395
const isTouched = fieldMetaValues.some((field) => field?.isTouched)
396+
const isBlurred = fieldMetaValues.some((field) => field?.isBlurred)
391397

392398
const isDirty = fieldMetaValues.some((field) => field?.isDirty)
393399
const isPristine = !isDirty
@@ -410,6 +416,7 @@ export class FormApi<
410416
isValid,
411417
canSubmit,
412418
isTouched,
419+
isBlurred,
413420
isPristine,
414421
isDirty,
415422
}
@@ -553,6 +560,12 @@ export class FormApi<
553560
// Mark them as touched
554561
field.instance.setMeta((prev) => ({ ...prev, isTouched: true }))
555562
}
563+
564+
// If any fields are not blurred
565+
if (!field.instance.state.meta.isBlurred) {
566+
// Mark them as blurred
567+
field.instance.setMeta((prev) => ({ ...prev, isBlurred: true }))
568+
}
556569
})
557570
})
558571

@@ -616,6 +629,12 @@ export class FormApi<
616629
fieldInstance.setMeta((prev) => ({ ...prev, isTouched: true }))
617630
}
618631

632+
// If the field is not blurred (same logic as in validateAllFields)
633+
if (!fieldInstance.state.meta.isBlurred) {
634+
// Mark it as blurred
635+
fieldInstance.setMeta((prev) => ({ ...prev, isBlurred: true }))
636+
}
637+
619638
return fieldInstance.validate(cause)
620639
}
621640

@@ -983,6 +1002,7 @@ export class FormApi<
9831002
acc[fieldKey] = {
9841003
isValidating: false,
9851004
isTouched: false,
1005+
isBlurred: false,
9861006
isDirty: false,
9871007
isPristine: true,
9881008
errors: [],
@@ -1009,6 +1029,7 @@ export class FormApi<
10091029
this.setFieldMeta(field, (prev) => ({
10101030
...prev,
10111031
isTouched: true,
1032+
isBlurred: true,
10121033
isDirty: true,
10131034
}))
10141035
}

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ describe('field api', () => {
4343

4444
expect(field.getMeta()).toEqual({
4545
isTouched: false,
46+
isBlurred: false,
4647
isValidating: false,
4748
isPristine: true,
4849
isDirty: false,
@@ -56,11 +57,17 @@ describe('field api', () => {
5657
const field = new FieldApi({
5758
form,
5859
name: 'name',
59-
defaultMeta: { isTouched: true, isDirty: true, isPristine: false },
60+
defaultMeta: {
61+
isTouched: true,
62+
isDirty: true,
63+
isPristine: false,
64+
isBlurred: true,
65+
},
6066
})
6167

6268
expect(field.getMeta()).toEqual({
6369
isTouched: true,
70+
isBlurred: true,
6471
isValidating: false,
6572
isDirty: true,
6673
isPristine: false,

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ describe('form api', () => {
1919
errorMap: {},
2020
isSubmitting: false,
2121
isTouched: false,
22+
isBlurred: false,
2223
isPristine: true,
2324
isDirty: false,
2425
isValid: true,
@@ -55,6 +56,7 @@ describe('form api', () => {
5556
isSubmitted: false,
5657
isSubmitting: false,
5758
isTouched: false,
59+
isBlurred: false,
5860
isPristine: true,
5961
isDirty: false,
6062
isValid: true,
@@ -89,6 +91,7 @@ describe('form api', () => {
8991
isSubmitted: false,
9092
isSubmitting: false,
9193
isTouched: false,
94+
isBlurred: false,
9295
isPristine: true,
9396
isDirty: false,
9497
isValid: true,
@@ -134,6 +137,7 @@ describe('form api', () => {
134137
isSubmitted: false,
135138
isSubmitting: false,
136139
isTouched: false,
140+
isBlurred: false,
137141
isPristine: true,
138142
isDirty: false,
139143
isValid: true,
@@ -178,6 +182,7 @@ describe('form api', () => {
178182
isSubmitted: false,
179183
isSubmitting: false,
180184
isTouched: false,
185+
isBlurred: false,
181186
isPristine: true,
182187
isDirty: false,
183188
isValid: true,
@@ -226,6 +231,7 @@ describe('form api', () => {
226231
name: {
227232
isValidating: false,
228233
isTouched: false,
234+
isBlurred: false,
229235
isDirty: false,
230236
isPristine: true,
231237
errors: [],
@@ -240,6 +246,7 @@ describe('form api', () => {
240246
isSubmitted: false,
241247
isSubmitting: false,
242248
isTouched: false,
249+
isBlurred: false,
243250
isPristine: true,
244251
isDirty: false,
245252
isValid: true,

0 commit comments

Comments
 (0)