sveltekit-superforms icon indicating copy to clipboard operation
sveltekit-superforms copied to clipboard

reset() doesn't work after schema change

Open rj-elias opened this issue 7 months ago • 4 comments

I am trying to reset the form manually with reset() and it doesn't work. Probably because the schema has changed in onSubmit

const { form, errors, message, enhance, reset, options } = superForm(data.form, {
		SPA: true,
		dataType: 'json',
		resetForm: false,
		validators: zod(schema),
		onSubmit: async ({ validators }) => {
			if (step === 1) {
				validators(zod(step1Schema))
			}

			if (step === 2) {
				validators(zod(step2Schema))
			}
		},
		onUpdate: async ({ form }) => {
			if (!form.valid) {
				setMessage(form, 'Invalid form')
				return
			}

			if (step === 1) {
				// API call
				step = 2
			}

			if (step === 2) {
				reset() // DOE NOT WORK. I believe this is because the schema has changed
			}
		}
	});

This doesn't work either

if (step === 2) {
        options.validators = zod(schema)
	reset()
}

rj-elias avatar Apr 11 '25 06:04 rj-elias

You cannot reset in onUpdate, as the stores will be updated afterwards. Try onUpdated instead, alternatively, use setTimeout.

ciscoheat avatar Apr 11 '25 07:04 ciscoheat

onUpdate: async ({ form }) => {
			if (!form.valid) {
				setMessage(form, 'Invalid form')
				return
			}

			if (step === 1) {
				// API call
				step = 2 // this state change depends on the response of the API call
			}
		},
		onUpdated: async () => {
			if (step === 2) {
				reset()
			}
		}

The form is reseted after step 1 is submitted. Looks like the state change for step happens before onUpdated run. step is updated to "2" then onUpdated runs with step = 2.

if (step === 1) {
	// API call
	step = 2
}

rj-elias avatar Apr 11 '25 07:04 rj-elias

In onUpdate, you can also make a manual reset by setting the properties of the form.data object to their empty values. But it may not be convenient if there are many properties, so setTimeout could be better, so you don't have to use both events.

ciscoheat avatar Apr 11 '25 08:04 ciscoheat

SvelteLab: https://www.sveltelab.dev/82kh1g8y213995d?files=.%2Fsrc%2Froutes%2F%2Bpage.svelte

Here is the UX/flow objective:

  1. Enter your email + submit
  2. Switch the schema to email only for validation
  3. After validation, the API call retrieves a token and update the "token" state
  4. Once the token is available in memory, the form move to step 2
  5. Enter the code + submit
  6. Switch the schema to code only for validation
  7. After validation, the API call post the code + the token in memory
  8. Once the API call is successful, reset the form
  • reset() in onUpdate doesn't reset the form since the store is updated afterward
  • form.data.email = '' doesn't work either. Is it because the schema is set to step2Schema?
  • Moving reset() to onUpdated doesn't work either since the token (hence, the step) is updated before onUpdated runs.
onSubmit: async ({ validators }) => {
	if (step === 1) {
		validators(zod(step1Schema))
	}

	if (step === 2) {
		validators(zod(step2Schema))
	}
},
onUpdate: async ({ form }) => {
	if (!form.valid) {
		setMessage(form, 'Invalid form')
		return
	}

	if (step === 1) {
		// API call returns a token
		const res = { token: 'token-state' }
		token = res.token
	}

	if (step === 2) {
                // Option 1, reset() ==>  when submitting the form in step 2, the form is not resetted
		reset()
                // Option 2, manually reset the form.data object ==> The form is resetted when submitting the step 1
		form.data.email = ''
		form.data.code = ''
	}
},

I don't quite get your suggestion with setTimeout though

rj-elias avatar Apr 11 '25 08:04 rj-elias