Skip to content

Commit ea91780

Browse files
committed
Refactor
1 parent 3541439 commit ea91780

File tree

2 files changed

+63
-76
lines changed

2 files changed

+63
-76
lines changed

packages/vue3/src/useForm.ts

Lines changed: 53 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ export default function useForm<TForm extends FormDataType<TForm>>(
191191
let recentlySuccessfulTimeoutId: ReturnType<typeof setTimeout>
192192
let transform: TransformCallback<TForm> = (data) => data
193193

194-
let validator: Validator | null = null
194+
let validatorRef: Validator | null = null
195195

196196
const parseSubmitArgs = (args: SubmitArgs): { method: Method; url: string; options: FormOptions } => {
197197
if (args.length === 3 || (args.length === 2 && typeof args[0] === 'string')) {
@@ -234,102 +234,79 @@ export default function useForm<TForm extends FormDataType<TForm>>(
234234
// Create validator - precognitionEndpoint is guaranteed to exist at this point
235235
const endpointCallback = precognitionEndpoint!
236236

237-
validator = createValidator((client) => {
237+
const validator = createValidator((client) => {
238238
const { method, url } = endpointCallback()
239239
const transformedData = transform(this.data()) as Record<string, unknown>
240240

241241
return client[method](url, transformedData)
242242
}, defaults)
243243

244-
// Store validator reference for type safety - after assignment, it's guaranteed to exist
245-
const validatorRef = validator
244+
validatorRef = validator
246245

247246
// Set up validator event handlers to sync state with form
248247
validator
249248
.on('validatingChanged', () => {
250-
formWithPrecognition.validating = validatorRef.validating()
249+
formWithPrecognition.validating = validator.validating()
251250
})
252251
.on('validatedChanged', () => {
253-
formWithPrecognition.__valid = validatorRef.valid()
252+
formWithPrecognition.__valid = validator.valid()
254253
})
255254
.on('touchedChanged', () => {
256-
formWithPrecognition.__touched = validatorRef.touched()
255+
formWithPrecognition.__touched = validator.touched()
257256
})
258257
.on('errorsChanged', () => {
259-
const validatorErrors = validatorRef.errors()
260258
const validationErrors = simpleValidationErrors
261-
? toSimpleValidationErrors(validatorErrors)
262-
: validatorErrors
259+
? toSimpleValidationErrors(validator.errors())
260+
: validator.errors()
263261

264-
// Clear existing errors and set new validation errors
265262
this.errors = {} as FormDataErrors<TForm>
266-
this.setError(validationErrors as FormDataErrors<TForm>)
267-
// Update valid state after errors change
268-
formWithPrecognition.__valid = validatorRef.valid()
269-
})
270-
271-
// Initialize precognition state
272-
formWithPrecognition.__touched = []
273-
formWithPrecognition.__valid = []
274-
formWithPrecognition.validating = false
275-
formWithPrecognition.validator = () => validatorRef
276263

277-
// Bind precognition methods - all return 'this' for method chaining
278-
formWithPrecognition.setValidationTimeout = (duration: number) => {
279-
validatorRef.setTimeout(duration)
280-
return formWithPrecognition
281-
}
282-
283-
formWithPrecognition.validateFiles = () => {
284-
validatorRef.validateFiles()
285-
return formWithPrecognition
286-
}
264+
this.setError(validationErrors as FormDataErrors<TForm>)
287265

288-
formWithPrecognition.withFullErrors = () => {
289-
simpleValidationErrors = false
290-
return formWithPrecognition
291-
}
266+
formWithPrecognition.__valid = validator.valid()
267+
})
292268

293-
formWithPrecognition.withoutFileValidation = () => {
294-
// @ts-expect-error - Not released yet...
295-
validatorRef.withoutFileValidation()
296-
return formWithPrecognition
269+
const tap = <T>(value: T, callback: (value: T) => unknown): T => {
270+
callback(value)
271+
return value
297272
}
298273

299-
formWithPrecognition.valid = (field: string) => formWithPrecognition.__valid.includes(field)
300-
formWithPrecognition.invalid = (field: string) => field in this.errors
301-
formWithPrecognition.validate = (
302-
field?: string | NamedInputEvent | ValidationConfig,
303-
config?: ValidationConfig,
304-
) => {
305-
// Handle config object passed as first argument
306-
if (typeof field === 'object' && !('target' in field)) {
307-
config = field
308-
field = undefined
309-
}
310-
311-
if (field === undefined) {
312-
validatorRef.validate(config)
313-
} else {
314-
const fieldName = resolveName(field)
315-
const transformedData = transform(this.data()) as Record<string, unknown>
316-
validatorRef.validate(fieldName, get(transformedData, fieldName), config)
317-
}
318-
319-
return formWithPrecognition
320-
}
274+
Object.assign(formWithPrecognition, {
275+
__touched: [],
276+
__valid: [],
277+
validating: false,
278+
validator: () => validator,
279+
withFullErrors: () => tap(formWithPrecognition, () => (simpleValidationErrors = false)),
280+
valid: (field: string) => formWithPrecognition.__valid.includes(field),
281+
invalid: (field: string) => field in this.errors,
282+
setValidationTimeout: (duration: number) => tap(formWithPrecognition, () => validator.setTimeout(duration)),
283+
validateFiles: () => tap(formWithPrecognition, () => validator.validateFiles()),
284+
withoutFileValidation: () =>
285+
// @ts-expect-error - Not released yet...
286+
tap(formWithPrecognition, () => validator.withoutFileValidation()),
287+
touch: (...fields: string[]) => tap(formWithPrecognition, () => validator.touch(fields)),
288+
touched: (field?: string): boolean =>
289+
typeof field === 'string'
290+
? formWithPrecognition.__touched.includes(field)
291+
: formWithPrecognition.__touched.length > 0,
292+
validate: (field?: string | NamedInputEvent | ValidationConfig, config?: ValidationConfig) => {
293+
// Handle config object passed as first argument
294+
if (typeof field === 'object' && !('target' in field)) {
295+
config = field
296+
field = undefined
297+
}
321298

322-
formWithPrecognition.touch = (...fields: string[]) => {
323-
validatorRef.touch(fields)
324-
return formWithPrecognition
325-
}
299+
if (field === undefined) {
300+
validator.validate(config)
301+
} else {
302+
const fieldName = resolveName(field)
303+
const transformedData = transform(this.data()) as Record<string, unknown>
304+
validator.validate(fieldName, get(transformedData, fieldName), config)
305+
}
326306

327-
formWithPrecognition.touched = (field?: string): boolean => {
328-
if (typeof field === 'string') {
329-
return formWithPrecognition.__touched.includes(field)
330-
}
331-
return formWithPrecognition.__touched.length > 0
332-
}
307+
return formWithPrecognition
308+
},
309+
})
333310

334311
return formWithPrecognition
335312
},
@@ -377,7 +354,7 @@ export default function useForm<TForm extends FormDataType<TForm>>(
377354
})
378355
}
379356

380-
validator?.reset(...fields)
357+
validatorRef?.reset(...fields)
381358

382359
return this
383360
},
@@ -388,7 +365,7 @@ export default function useForm<TForm extends FormDataType<TForm>>(
388365

389366
this.hasErrors = Object.keys(this.errors).length > 0
390367

391-
validator?.setErrors(errors as Errors)
368+
validatorRef?.setErrors(errors as Errors)
392369

393370
return this
394371
},
@@ -403,11 +380,11 @@ export default function useForm<TForm extends FormDataType<TForm>>(
403380

404381
this.hasErrors = Object.keys(this.errors).length > 0
405382

406-
if (validator) {
383+
if (validatorRef) {
407384
if (fields.length === 0) {
408-
validator.setErrors({})
385+
validatorRef.setErrors({})
409386
} else {
410-
fields.forEach(validator.forgetError)
387+
fields.forEach(validatorRef.forgetError)
411388
}
412389
}
413390

packages/vue3/test-app/Pages/FormHelper/TypeScript/Precognition.vue

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,14 @@ precognitionForm.touched('email')
3737
precognitionForm.invalid('email')
3838
// @ts-expect-error - Field does not exist
3939
precognitionForm.valid('email')
40+
41+
const nestedForm = useForm({ user: { name: '', company: '' } }).withPrecognition('post', '/precognition/nested')
42+
43+
nestedForm.valid('user.name')
44+
nestedForm.invalid('user.name')
45+
46+
// @ts-expect-error - Field does not exist
47+
nestedForm.valid('user.email')
48+
// @ts-expect-error - Field does not exist
49+
nestedForm.invalid('user.email')
4050
</script>

0 commit comments

Comments
 (0)