99 SubmitEvent ,
1010 ValidationResult ,
1111 MaybeReactive ,
12+ FormState ,
1213} from './types' ;
1314import { getFromPath , isYupValidator , keysOf , setInPath , unsetPath } from './utils' ;
1415import { FormErrorsSymbol , FormInitialValues , FormSymbol } from './symbols' ;
@@ -85,7 +86,11 @@ export function useForm<TValues extends Record<string, any> = Record<string, any
8586 } ) ;
8687
8788 // initial form values
88- const { initialValues } = useFormInitialValues < TValues > ( fieldsById , formValues , opts ?. initialValues ) ;
89+ const { initialValues, setInitialValues } = useFormInitialValues < TValues > (
90+ fieldsById ,
91+ formValues ,
92+ opts ?. initialValues
93+ ) ;
8994
9095 // form meta aggregations
9196 const meta = useFormMeta ( fields , initialValues ) ;
@@ -213,8 +218,25 @@ export function useForm<TValues extends Record<string, any> = Record<string, any
213218 /**
214219 * Resets all fields
215220 */
216- const handleReset = ( ) => {
221+ const reset = ( state ?: Partial < FormState < TValues > > ) => {
222+ // set initial values if provided
223+ if ( state ?. values ) {
224+ setInitialValues ( state . values ) ;
225+ }
226+
227+ // Reset all fields state
217228 fields . value . forEach ( ( f : any ) => f . reset ( ) ) ;
229+
230+ // set explicit state afterwards
231+ if ( state ?. dirty ) {
232+ setDirty ( state . dirty ) ;
233+ }
234+ if ( state ?. touched ) {
235+ setTouched ( state . touched ) ;
236+ }
237+ if ( state ?. errors ) {
238+ setErrors ( state . errors ) ;
239+ }
218240 } ;
219241
220242 function registerField ( field : FieldComposite ) {
@@ -294,7 +316,7 @@ export function useForm<TValues extends Record<string, any> = Record<string, any
294316 setTouched,
295317 setFieldDirty,
296318 setDirty,
297- reset : handleReset ,
319+ reset,
298320 } ;
299321
300322 const validate = async ( ) => {
@@ -375,7 +397,6 @@ export function useForm<TValues extends Record<string, any> = Record<string, any
375397 } ) ;
376398
377399 // Provide injections
378- provide ( FormInitialValues , initialValues ) ;
379400 provide ( FormSymbol , formCtx as FormContext ) ;
380401 provide ( FormErrorsSymbol , errors ) ;
381402
@@ -385,7 +406,8 @@ export function useForm<TValues extends Record<string, any> = Record<string, any
385406 values : formValues ,
386407 validate,
387408 isSubmitting,
388- handleReset,
409+ handleReset : ( ) => reset ( ) ,
410+ resetForm : reset ,
389411 handleSubmit,
390412 submitForm,
391413 setFieldError,
@@ -482,43 +504,59 @@ async function validateYupSchema<TValues>(
482504/**
483505 * Manages the initial values prop
484506 */
485- function useFormInitialValues < TValues > (
507+ function useFormInitialValues < TValues extends Record < string , any > > (
486508 fields : Ref < Record < keyof TValues , any > > ,
487509 formValues : TValues ,
488510 providedValues ?: MaybeReactive < TValues >
489511) {
490- const initialValues = computed < TValues > ( ( ) => {
491- if ( isRef ( providedValues ) ) {
492- return providedValues . value ;
493- }
494-
495- return providedValues || ( { } as TValues ) ;
512+ const initialValues = ref < TValues > ( ( unref ( providedValues ) as TValues ) || ( { } as TValues ) ) ;
513+ // acts as a read only proxy of the initial values object
514+ const computedInitials = computed < TValues > ( ( ) => {
515+ return initialValues . value as TValues ;
496516 } ) ;
497517
498- // Watch initial values for changes, and update the pristine (non-dirty and non-touched fields)
499- // we exclude dirty and untouched fields because it's unlikely you want to change the form values using initial values
500- // we mostly watch them for API population or newly inserted fields
501- watch (
502- initialValues ,
503- value => {
504- const isSafeToUpdate = ( f : any ) => f . meta . dirty || f . meta . touched ;
505- keysOf ( fields . value ) . forEach ( fieldPath => {
506- const field = fields . value [ fieldPath ] ;
507- const isFieldDirty = Array . isArray ( field ) ? field . some ( isSafeToUpdate ) : isSafeToUpdate ( field ) ;
508- if ( isFieldDirty ) {
509- return ;
510- }
518+ function setInitialValues ( values : Partial < TValues > , updateFields = false ) {
519+ initialValues . value = {
520+ ...initialValues . value ,
521+ ...values ,
522+ } ;
511523
512- const newValue = getFromPath ( value , fieldPath as string ) ;
513- setInPath ( formValues , fieldPath as string , newValue ) ;
514- } ) ;
515- } ,
516- {
517- deep : true ,
524+ if ( ! updateFields ) {
525+ return ;
518526 }
519- ) ;
527+
528+ // update the pristine (non-dirty and non-touched fields)
529+ // we exclude dirty and untouched fields because it's unlikely you want to change the form values using initial values
530+ // we mostly watch them for API population or newly inserted fields
531+ const isSafeToUpdate = ( f : any ) => f . meta . dirty || f . meta . touched ;
532+ keysOf ( fields . value ) . forEach ( fieldPath => {
533+ const field = fields . value [ fieldPath ] ;
534+ const isFieldDirty = Array . isArray ( field ) ? field . some ( isSafeToUpdate ) : isSafeToUpdate ( field ) ;
535+ if ( isFieldDirty ) {
536+ return ;
537+ }
538+
539+ const newValue = getFromPath ( initialValues . value , fieldPath as string ) ;
540+ setInPath ( formValues , fieldPath as string , newValue ) ;
541+ } ) ;
542+ }
543+
544+ if ( isRef ( providedValues ) ) {
545+ watch (
546+ providedValues ,
547+ value => {
548+ setInitialValues ( value , true ) ;
549+ } ,
550+ {
551+ deep : true ,
552+ }
553+ ) ;
554+ }
555+
556+ provide ( FormInitialValues , computedInitials ) ;
520557
521558 return {
522- initialValues,
559+ initialValues : computedInitials ,
560+ setInitialValues,
523561 } ;
524562}
0 commit comments