Search code examples
sveltesveltekit

Sveltekit form actions not returning data when invoked from different route


I'm having issues loading form action response data in Sveltekit, when the form is submitted from a different route to the server action.

The Sveltekit app has the following structure:

/lib
  MyForm.svelte
/routes
  /pageA
    +page.svelte
    +page.server.ts
  /pageB
    +page.svelte
// /routes/pageA/+page.server.ts
export const actions: Actions = {
  myAction: async () => {
    console.log('Form action triggered');
    // Do things...
    return { success: true, data: 'Result data' }
  }
};
<!-- /lib/MyForm.svelte -->
<script lang="ts">
  import { enhance } from '$app/forms';
  import { page } from '$app/stores';
  import type { SubmitFunction } from '@sveltejs/kit';

  const mySubmitFunction: SubmitFunction = () => {
        console.log('Form Submitted');
        return async ({ update }) => {
            await update();
            console.log('Server has responded');
            console.log($page?.form);
        };
    };
</script>

<form
  method="POST"
  action="/pageA?/myAction"
  use:enhance={mySubmitFunction}
>
  <button type="submit">Submit</button>
</form>

When MyForm.svelte is imported into pageA/+page.svelte, everything runs correctly, and $page?.form is updated with the return data. However, when the form is imported into pageB/+page.svelte, no form data is returned - $page?.form remains null. The action still runs on the client and server side - the console still logs the appropriate messages.

Is this a bug in Sveltekit, or am I missing something here?

EDIT As per the documentation and @brunnerh's answer, updated MyForm.svelte:

<script lang="ts">
  import { enhance, applyAction } from '$app/forms';
  import { goto } from '$app/navigation';
  ...

  const mySubmitFunction: SubmitFunction = () => {
          console.log('Form Submitted');
          return async ({ update, result }) => {
              await update();
              if (result.type === 'redirect') {
                await goto(result.location)
              } else {
                await applyAction(result);
              }
              console.log('Server has responded');
              console.log($page?.form); // Now correctly prints form result
          };
      };
</script>
...

Solution

  • This is intentional, see docs on use:enhance, the default update logic contains:

    update the form property, $page.form and $page.status on a successful or invalid response, but only if the action is on the same page you're submitting from. For example, if your form looks like <form action="/somewhere/else" ..>, form and $page will not be updated. This is because in the native form submission case you would be redirected to the page the action is on. If you want to have them updated either way, use applyAction