[Bug]: formState.isDirty is still false after pushing into a field array
Which packages are impacted?
- [x]
@rvf/react - [x]
@rvf/react-router - [ ]
@rvf/zod - [ ]
@rvf/yup - [ ]
zod-form-data
What version of these packages are you using?
-
@rvf/react7.1.2
Please provide a link to a minimal reproduction of the issue.
https://codesandbox.io/p/sandbox/vzr6j9
Steps to Reproduce the Bug or Issue
In the codesandbox reproduction, click the Push button. The isDirty form state should switch to true, but it doesn't. You have to dirty the field itself first.
Expected behavior
The form itself should be dirty after modifying a field array, even if the fields inside the field array item aren't actually dirty.
Screenshots or Videos
No response
Platform
- OS: Mac
- Browser: Arc
- Version: 1.91.0
Additional context
No response
Hello :),
I'm facing a similar issue on RVF 8. The form isDirty remains false after adding or deleting array items. Have you find a workaround?
Hello :),
I'm facing a similar issue on RVF 8. The form isDirty remains false after adding or deleting array items. Have you find a workaround?
Hi!
As a temporary workaround, you could update the dirty state manually: form.setDirty("myFieldArray", true). Not ideal, but gets the job done until the bug is fixed.
Thanks for the trick! This works but this is not optimal though. First you need to carry the form in the component (I am using the scope and field to only pass to components the fields they need, so I don't have access to the parent form). Secondly, as soon as you put it dirty, if the user reconfigure the array to the previous state it will stay dirty while the user might have revert to a non-dirty state.
First you need to carry the form in the component (I am using the scope and field to only pass to components the fields they need, so I don't have access to the parent form).
If you're passing a scope, you can do this to get access to the form api:
const formApi = useFormScope(myScope);
And all the helpers are scoped down to that part of the form. No need to pass a form-level api explicitly.
This is not working @airjp73 . While you can go down (so creating a scope from a form), you cannot revert back a scope to its original form (when you do so then the form become empty). Said otherwise this won't work:
// In parent component
<Foo scope={form.scope('foo')} />
// In foo.ts component:
const formApi = useFormScope(scope);
// formApi is not the same as the original form
you cannot revert back a scope to its original form
That's correct, but also isn't necessary. Here's an example of how this would be used to update the dirty state of the foo field:
const base = useForm(/* etc */);
const foo = useFormScope(base.scope('foo'));
// this
foo.setDirty(true);
// is equivalent to this
base.setDirty("foo", true);
Going back to the original field array use-case, you might do something like this:
const MyForm = () => {
const form = useForm(/* etc */);
return <MyArray scope={form.scope("myArray")} />
}
const MyArray = ({ scope }) => {
const array = useFieldArray(scope);
const formApi = useFormScope(scope);
return (
<ul>
{array.map((key, item) => (
<MyItem key={key} scope={item.scope()} />
))}
<button
type="button"
onClick={() => {
array.push("");
formApi.setDirty(true);
}}
>
Add item
</button>
</ul>
);
}
For reference, this issue happens for all array methods (such as move, swap, remove) and not just push.
Just to comment back on this, the workaround, while working, is quite confusing. Having to deal with lot of different elements (a scope, a "field array", a "form scope"...) is confusing. I have a component when I have two scopes as a parameter, so I need to create two "fieldArray", two "formApi". I tried to check if I could fix the issue myself in the library as this makes RVF quite painful to use whenever array are involved (unfortunately, all my forms in this projects have forms) but for some strange reason I could not run the test suite (I have some errors that I could not understand).