Skip to content

Commit

Permalink
fix: mark form dirty when object keys are deleted
Browse files Browse the repository at this point in the history
Fixes logaretm#4678

This fix has been co-authored by @SCBosch.
  • Loading branch information
evpaassen committed Mar 22, 2024
1 parent 2a0881f commit b83365b
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 1 deletion.
21 changes: 20 additions & 1 deletion packages/vee-validate/src/utils/assertions.ts
Expand Up @@ -108,6 +108,8 @@ export function isPropPresent(obj: Record<string, unknown>, prop: string) {
* Compares if two values are the same borrowed from:
* https://github.com/epoberezkin/fast-deep-equal
* We added a case for file matching since `Object.keys` doesn't work with Files.
*
* NB: keys with the value undefined are ignored in the evaluation and considered equal to missing keys.
* */
export function isEqual(a: any, b: any) {
if (a === b) return true;
Expand Down Expand Up @@ -162,7 +164,13 @@ export function isEqual(a: any, b: any) {
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();

keys = Object.keys(a);
length = keys.length;
length = keys.length - countUndefinedValues(a, keys);

if (length !== Object.keys(b).length - countUndefinedValues(b, Object.keys(b))) return false;

for (i = length; i-- !== 0; ) {
if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
}

for (i = length; i-- !== 0; ) {
// eslint-disable-next-line no-var
Expand All @@ -179,6 +187,17 @@ export function isEqual(a: any, b: any) {
return a !== a && b !== b;
}

function countUndefinedValues(a: any, keys: string[]) {
let result = 0;
for (let i = keys.length; i-- !== 0; ) {
// eslint-disable-next-line no-var
var key = keys[i];

if (a[key] === undefined) result++;
}
return result;
}

export function isFile(a: unknown): a is File {
if (!isClient) {
return false;
Expand Down
26 changes: 26 additions & 0 deletions packages/vee-validate/tests/useForm.spec.ts
Expand Up @@ -1133,6 +1133,32 @@ describe('useForm()', () => {
expect(form.meta.value.dirty).toBe(false);
});

// #4678
test('form is marked as dirty when key is removed', async () => {
let form!: FormContext<any>;
mountWithHoc({
setup() {
form = useForm({
initialValues: {
fname: {
key1: 'value1',
key2: 'value2',
},
},
});

useField('fname');

return {};
},
template: `<div></div>`,
});

form.setFieldValue('fname', { key1: 'value1' });
await flushPromises();
expect(form.meta.value.dirty).toBe(true);
});

describe('error paths can have dot or square bracket for the same field', () => {
test('path is bracket, mutations are dot', async () => {
let field!: FieldContext<unknown>;
Expand Down

0 comments on commit b83365b

Please sign in to comment.