From 74d682cffbd312aae0e9c2a235eaa022b1133123 Mon Sep 17 00:00:00 2001 From: Jonathan Reinink Date: Tue, 24 Oct 2023 21:25:04 -0400 Subject: [PATCH] Clear errors on form reset (#1568) * Clear errors on form reset * Abstract out `clearErrors` function * Update tests * Fix test * Update changelog --- CHANGELOG.md | 2 +- packages/react/src/useForm.ts | 31 +++++++++++-------- packages/svelte/src/useForm.js | 4 ++- packages/vue2/src/useForm.ts | 2 ++ .../cypress/integration/form-helper.test.js | 18 +++++------ .../cypress/integration/remember.test.js | 4 +-- packages/vue3/src/useForm.ts | 2 ++ 7 files changed, 37 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96f23bfd1..bdcda3c64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ For changes prior to v1.0.0, see the [legacy releases](https://legacy.inertiajs. ## [Unreleased](https://github.com/inertiajs/inertia/compare/v1.0.12...HEAD) -- Nothing! +- Clear errors on form reset ([#1568](https://github.com/inertiajs/inertia/pull/1568)) ## [v1.0.12](https://github.com/inertiajs/inertia/compare/v1.0.11...v1.0.12) diff --git a/packages/react/src/useForm.ts b/packages/react/src/useForm.ts index 22af09f4a..6e88ac049 100644 --- a/packages/react/src/useForm.ts +++ b/packages/react/src/useForm.ts @@ -166,6 +166,20 @@ export default function useForm( [data, setErrors], ) + function clearErrors(...fields) { + setErrors((errors) => { + const newErrors = (Object.keys(errors) as Array).reduce( + (carry, field) => ({ + ...carry, + ...(fields.length > 0 && !fields.includes(field) ? { [field]: errors[field] } : {}), + }), + {}, + ) + setHasErrors(Object.keys(newErrors).length > 0) + return newErrors + }) + } + return { data, setData(keyOrData: keyof TForm | Function | TForm, maybeValue?: TForm[keyof TForm]) { @@ -200,6 +214,8 @@ export default function useForm( reset(...fields) { if (fields.length === 0) { setData(defaults) + setErrors({}) + setHasErrors(false) } else { setData( (Object.keys(defaults) as Array) @@ -212,6 +228,7 @@ export default function useForm( { ...data }, ), ) + clearErrors(...fields) } }, setError(fieldOrFields: keyof TForm | Record, maybeValue?: string) { @@ -226,19 +243,7 @@ export default function useForm( return newErrors }) }, - clearErrors(...fields) { - setErrors((errors) => { - const newErrors = (Object.keys(errors) as Array).reduce( - (carry, field) => ({ - ...carry, - ...(fields.length > 0 && !fields.includes(field) ? { [field]: errors[field] } : {}), - }), - {}, - ) - setHasErrors(Object.keys(newErrors).length > 0) - return newErrors - }) - }, + clearErrors, submit, get(url, options) { submit('get', url, options) diff --git a/packages/svelte/src/useForm.js b/packages/svelte/src/useForm.js index d624f65d6..37978c1ad 100644 --- a/packages/svelte/src/useForm.js +++ b/packages/svelte/src/useForm.js @@ -1,6 +1,6 @@ import { router } from '@inertiajs/core' -import isEqual from 'lodash.isequal' import cloneDeep from 'lodash.clonedeep' +import isEqual from 'lodash.isequal' import { writable } from 'svelte/store' function useForm(...args) { @@ -52,6 +52,7 @@ function useForm(...args) { let clonedDefaults = cloneDeep(defaults) if (fields.length === 0) { this.setStore(clonedDefaults) + this.clearErrors() } else { this.setStore( Object.keys(clonedDefaults) @@ -61,6 +62,7 @@ function useForm(...args) { return carry }, {}), ) + this.clearErrors(...fields) } return this diff --git a/packages/vue2/src/useForm.ts b/packages/vue2/src/useForm.ts index 20a2ebc25..4b7bf1a01 100644 --- a/packages/vue2/src/useForm.ts +++ b/packages/vue2/src/useForm.ts @@ -88,6 +88,7 @@ export default function useForm(...args): InertiaFor if (fields.length === 0) { defaults = clonedData Object.assign(this, resolvedData) + this.clearErrors() } else { Object.keys(resolvedData) .filter((key) => fields.includes(key)) @@ -95,6 +96,7 @@ export default function useForm(...args): InertiaFor defaults[key] = clonedData[key] this[key] = resolvedData[key] }) + this.clearErrors(...fields) } return this diff --git a/packages/vue2/tests/cypress/integration/form-helper.test.js b/packages/vue2/tests/cypress/integration/form-helper.test.js index c0b05208e..a872cdd97 100644 --- a/packages/vue2/tests/cypress/integration/form-helper.test.js +++ b/packages/vue2/tests/cypress/integration/form-helper.test.js @@ -340,7 +340,7 @@ describe('Form Helper', () => { cy.get('#remember').should('be.checked') }) - it('does not reset errors when it resets a field to its initial value', () => { + it('resets error when it resets a field to its initial value', () => { cy.get('#name').clear().type('A') cy.get('#handle').clear().type('B') cy.get('#remember').check() @@ -361,11 +361,11 @@ describe('Form Helper', () => { cy.get('#remember').should('be.checked') cy.get('.errors-status').should('have.text', 'Form has errors') cy.get('.name_error').should('have.text', 'Some name error') - cy.get('.handle_error').should('have.text', 'The Handle was invalid') + cy.get('.handle_error').should('not.exist') cy.get('.remember_error').should('not.exist') }) - it('does not reset errors when it resets all fields to their initial values', () => { + it('reset errors when it resets all fields to their initial values', () => { cy.get('#name').clear().type('A') cy.get('#handle').clear().type('B') cy.get('#remember').check() @@ -379,14 +379,14 @@ describe('Form Helper', () => { cy.get('.name_error').should('have.text', 'Some name error') cy.get('.handle_error').should('have.text', 'The Handle was invalid') - cy.get('.reset-one').click() + cy.get('.reset').click() - cy.get('#name').should('have.value', 'A') + cy.get('#name').should('have.value', 'foo') cy.get('#handle').should('have.value', 'example') - cy.get('#remember').should('be.checked') - cy.get('.errors-status').should('have.text', 'Form has errors') - cy.get('.name_error').should('have.text', 'Some name error') - cy.get('.handle_error').should('have.text', 'The Handle was invalid') + cy.get('#remember').should('not.be.checked') + cy.get('.errors-status').should('have.text', 'Form has no errors') + cy.get('.name_error').should('not.exist') + cy.get('.handle_error').should('not.exist') cy.get('.remember_error').should('not.exist') }) diff --git a/packages/vue2/tests/cypress/integration/remember.test.js b/packages/vue2/tests/cypress/integration/remember.test.js index 93fa31019..b5baf7c3b 100644 --- a/packages/vue2/tests/cypress/integration/remember.test.js +++ b/packages/vue2/tests/cypress/integration/remember.test.js @@ -273,7 +273,7 @@ describe('Remember (local state caching)', () => { cy.get('#remember').should('be.checked') cy.get('#untracked').should('have.value', 'C') // Unchanged from above cy.get('.name_error').should('not.exist') - cy.get('.handle_error').should('have.text', 'The Handle was invalid') + cy.get('.handle_error').should('not.exist') cy.get('.remember_error').should('not.exist') cy.get('.link').click() @@ -287,7 +287,7 @@ describe('Remember (local state caching)', () => { cy.get('#remember').should('be.checked') cy.get('#untracked').should('not.have.value', 'C') // Untracked, so now reset (page state was lost) cy.get('.name_error').should('not.exist') - cy.get('.handle_error').should('have.text', 'The Handle was invalid') + cy.get('.handle_error').should('not.exist') cy.get('.remember_error').should('not.exist') }) }) diff --git a/packages/vue3/src/useForm.ts b/packages/vue3/src/useForm.ts index d617a80c7..665eaf794 100644 --- a/packages/vue3/src/useForm.ts +++ b/packages/vue3/src/useForm.ts @@ -95,6 +95,7 @@ export default function useForm( if (fields.length === 0) { defaults = clonedData Object.assign(this, resolvedData) + this.clearErrors() } else { Object.keys(resolvedData) .filter((key) => fields.includes(key)) @@ -102,6 +103,7 @@ export default function useForm( defaults[key] = clonedData[key] this[key] = resolvedData[key] }) + this.clearErrors(...fields) } return this