Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using superForm with $derived #396

Open
1 task done
unlocomqx opened this issue Apr 5, 2024 · 12 comments · May be fixed by #401
Open
1 task done

Using superForm with $derived #396

unlocomqx opened this issue Apr 5, 2024 · 12 comments · May be fixed by #401
Labels
bug Something isn't working later May be worked on in the future. svelte-5 Related to Svelte 5
Milestone

Comments

@unlocomqx
Copy link

  • Before posting an issue, read the FAQ and search the previous issues.

Description
I tried retuning multiple superforms in an array, but I could not use it in the frontend.
The only convenient way was to destructure each superform in the each tag but svelte doesn't support "declaring" stores out of the top-level of the component

If applicable, a MRE
https://www.sveltelab.dev/9tdm9ul193m3tz5

@unlocomqx unlocomqx added the bug Something isn't working label Apr 5, 2024
@unlocomqx
Copy link
Author

unlocomqx commented Apr 5, 2024

It didn't occur to me to extract the form into a separate component 🤦
So this would work

{#each superforms as superform}
	<Comp {superform} />
{/each}

Closing.

@unlocomqx
Copy link
Author

I'm reopening this issue because I encountered a problem

When I write this code

<script>
const superforms = data.my_forms.map((form) =>
	superForm(form, {
		dataType: 'json'
	})
);
</script>
{#each superforms as superform (superform.formId)}
	<ConditionItem {superform} />
{/each}

It works well but when a new form is added, then that's where I run into a problem

If I try to use $derived

const superforms = $derived(
	data.condition_forms.map((form) =>
		superForm(form, {
			dataType: 'json'
		})
	)
);

I get this error

Uncaught Error: onDestroy can only be used during component initialisation.

Repro https://www.sveltelab.dev/9tdm9ul193m3tz5

  • Click the Add button to add a new item (thus a new form)

@unlocomqx unlocomqx reopened this Apr 6, 2024
@unlocomqx
Copy link
Author

I found a way to fix it, I pushed my code here

If you'd like, I can make a PR for this

Cheers

@ciscoheat
Copy link
Owner

A PR for this would be very nice!

@unlocomqx
Copy link
Author

Okay, I will send a PR for this

@unlocomqx unlocomqx linked a pull request Apr 7, 2024 that will close this issue
@ciscoheat ciscoheat added later May be worked on in the future. svelte-5 Related to Svelte 5 labels Apr 23, 2024
@ciscoheat
Copy link
Owner

ciscoheat commented Apr 23, 2024

The problem is bigger than I anticipated, it'll require an overhaul of the onDestroy/cleanup handling. It'll have to wait until later. For now, calling superForm within $derived is not possible.

@unlocomqx
Copy link
Author

Okay, it will be good to have dynamic forms in the future. I will try to find a workaround for now.

@snide
Copy link

snide commented Jul 20, 2024

Out of curiosity, what is the proscribed workaround for this? Just not to use superforms for an array of forms? Seems common to have a list of things, then have to a button to delete them individually...etc. Are folks just making client side individual API posts here for now?

@unlocomqx
Copy link
Author

unlocomqx commented Jul 20, 2024

There's an example here

How to use Superforms with actions on a list of data.

Although, I prefer not using the formId and instead get the submitter and alter the submitted data based on its props.

I also only submit tainted rows as I only need to save the text fields that the user modified.

Sample code below

const {
	....
} = superForm(data.fields_form, {
	dataType: 'json',
	resetForm: false,
	onSubmit({ submitter, jsonData }) {
		const action = submitter?.getAttribute('name') || 'update'
		const action_value = submitter?.getAttribute('value') || ''
		jsonData({
			...$form,
			action,
			action_value,
			fields: Object.fromEntries(
				Object.values($form.fields)
					.filter((f) =>
						Object.keys($tainted?.fields ?? {}).includes(f.id.toString()),
					)
					.map((f) => [ f.id, f ]),
			),
		})
	},
})

@snide
Copy link

snide commented Jul 20, 2024

Terribly embarrassed to say I missed that entire examples page. You made my day. TY!

@ciscoheat ciscoheat added this to the v3 milestone Aug 11, 2024
@ciscoheat ciscoheat changed the title Usability problem of an array of superforms Using superForm with $derived Aug 11, 2024
@MerlinB
Copy link

MerlinB commented Oct 18, 2024

Am I correct in assuming that this means that in Svelte 5 pre-filled forms will never update after submitting as the invalidated load function reruns but the form wont update unless wrapped in $derived, which isn't possible either?

So the only way then to use pre-filled forms in Svelte 5 seems to be to use

    invalidateAll: false,
    resetForm: false,

@ciscoheat
Copy link
Owner

As long as you don't call superForm in $derived, it should work fine. A workaround for the array example is to call superForm for each data in a component instead, sending the SuperValidated form data as a prop:

{#each data.my_forms as form}
  <ConditionForm {form} />
{/each}

See the componentization guide for more info.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working later May be worked on in the future. svelte-5 Related to Svelte 5
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants