@@ -400,11 +400,6 @@ export function useForm<TValues extends Record<string, any> = Record<string, any
400400
401401 fieldAtPath . splice ( idx , 1 ) ;
402402
403- if ( fieldAtPath . length === 1 ) {
404- fieldsByPath . value [ fieldPath ] = fieldAtPath [ 0 ] ;
405- return ;
406- }
407-
408403 if ( ! fieldAtPath . length ) {
409404 delete fieldsByPath . value [ fieldPath ] ;
410405 }
@@ -458,17 +453,39 @@ export function useForm<TValues extends Record<string, any> = Record<string, any
458453 const isGroup = ! ! fieldInstance && isFieldGroup ( fieldInstance ) ;
459454 removeFieldFromPath ( field , fieldName ) ;
460455
456+ // clears a field error on unmounted
457+ // we wait till next tick to make sure if the field is completely removed and doesn't have any siblings like checkboxes
461458 nextTick ( ( ) => {
462- // clears a field error on unmounted
463- // we wait till next tick to make sure if the field is completely removed and doesn't have any siblings like checkboxes
459+ const shouldKeepValue = unref ( field . keepValueOnUnmount ) ?? unref ( keepValuesOnUnmount ) ;
460+ const currentGroupValue = getFromPath ( formValues , fieldName ) ;
461+ // The boolean here is we check if the field still belongs to the same control group with that name
462+ // if another group claimed the name, we should avoid handling it since it is no longer the same group
463+ // this happens with `v-for` over some checkboxes and field arrays.
464+ // also if the group no longer exist we can assume this group was the last one that controlled it
465+ const isSameGroup =
466+ isGroup && ( fieldInstance === fieldsByPath . value [ fieldName ] || ! fieldsByPath . value [ fieldName ] ) ;
467+
468+ // group field that still has a dangling value, the field may exist or not after it was removed.
469+ // This used to be handled in the useField composable but the form has better context on when it should/not happen.
470+ // if it does belong to it that means the group still exists
471+ // #3844
472+ if ( isSameGroup && Array . isArray ( currentGroupValue ) && ! shouldKeepValue ) {
473+ const valueIdx = currentGroupValue . findIndex ( i => isEqual ( i , unref ( field . checkedValue ) ) ) ;
474+ if ( valueIdx > - 1 ) {
475+ const newVal = [ ...currentGroupValue ] ;
476+ newVal . splice ( valueIdx , 1 ) ;
477+ setFieldValue ( fieldName , newVal as any , { force : true } ) ;
478+ }
479+ }
480+
481+ // Field was removed entirely, we should unset its path
464482 // #3384
465483 if ( ! fieldExists ( fieldName ) ) {
466484 setFieldError ( fieldName , undefined ) ;
467485
468486 // Checks if the field was configured to be unset during unmount or not
469487 // Checks both the form-level config and field-level one
470488 // Field has the priority if it is set, otherwise it goes to the form settings
471- const shouldKeepValue = unref ( field . keepValueOnUnmount ) ?? unref ( keepValuesOnUnmount ) ;
472489 if ( shouldKeepValue ) {
473490 return ;
474491 }
0 commit comments