- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 2.1k
feat: remote form factory #14815
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
base: main
Are you sure you want to change the base?
feat: remote form factory #14815
Conversation
| 🦋 Changeset detectedLatest commit: ec5cb13 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
 Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR | 
| thank you! I think something like this may make sense. I haven't talked with the other maintainers yet, but maybe we could go one step further and decouple all the client-side goodies from the core which is just about posting a form to the backend. As a result you would call some function, pass the remote function in, and can also pass initial values at the same time there, etc. Could be nice for treeshaking and more involved scenarios but could also be a bit less ergonomic in the simple case (this one, too, btw), so we'll see. | 
| That also sounds good. This was just the simplest change from the existing logic, thus making the migration easier.  | 
| @dummdidumm Regarding ergonomics: I would say that the mental model for calling a function to create the form would feel more natural to me. import { dataForm, getData } from './some.remote';
const { params } = $props();
// derived needed because of params.id dependency
const data = $derived(await getData(params.id));
// how to set the init data???
// 1. this would not be reactive
dataForm.fields.set(data)
// 2. this would not run server side
$effect(() => {
    dataForm.fields.set(data)
})
// 3. set every field by hand... very unhandy and doesn't scale
<input {...dataForm.fields.text.as("text")} value={data.text} />The function call solves this, and feels more ergonomic to me. import { dataForm, getData } from './some.remote';
const { params } = $props();
// get the data dependent on id
const data = $derived(await getData(params.id));
// create the form dependent on data
const form = $derived(dataForm({
   initialData: data
})Another benefit of the factory: reduce manually setting attributes on the form like multipart: <!-- current way -->
<form {...dataForm} enctype="multipart/form-data"></form><script>
import { dataForm, getData } from './some.remote';
const form = dataForm({
    // simpler for the user, and could be typed
    multipart: true
})
</script>
<!-- form can now set the correct enctype -->
<form {...form}></form> | 
| 
 Another benefit of a stand alone client side form model would be, that we could use it with other datasources that are not remote functions. We write tons of SPAs where SvelteKit is used with adapter-static. | 
fixes #14802
fixes #14787
According to the docs, the result is supposed to be
But that is not currently the case for navigating. The same is true of the values, issues, etc.
When you import a remote form into a page, you're importing an instance of the form. That instance is cached in memory so all properties tied to it are preserved when you navigate from page to page.
This PR changes the import into a factory function that creates a new instance each time the page/component loads, and removes the instance when it unloads.
Demo: https://stackblitz.com/edit/sveltekit-template-sjtkof-etscgbpf?file=package.json,src%2Froutes%2F%2Bpage.svelte
<script lang="ts"> import { todo } from "./form.remote.ts"; </script> - <form {...todo}> <!-- same instance every time --> + <form {...todo()}> <!-- creates a new instance --> ... </form>And instead of
.for(), you can now pass the key to the function.This also opens up the possibility of making the form configurable like this:
Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
Tests
pnpm testand lint the project withpnpm lintandpnpm checkChangesets
pnpm changesetand following the prompts. Changesets that add features should beminorand those that fix bugs should bepatch. Please prefix changeset messages withfeat:,fix:, orchore:.Edits