Skip to content

Latest commit

 

History

History
87 lines (76 loc) · 2.26 KB

form.md

File metadata and controls

87 lines (76 loc) · 2.26 KB

Use with SvelteKit use:enhance

🚧 Work in Progress

Modal with a <form use:enhance> child element

  • Modal should not be closable during submission
  • Form reset should follow the browser behaviors
  • Submitting state should last for a minimum time
<script>
  import { enhance } from '$app/forms';
  import { tick } from 'svelte';
  import { Modal } from 'svelte-html-modal';

  export let form;

  let showModal = false;

  /** @type {'submitting' | 'submitted' | null} */
  let formState = null;
</script>

<button type="button" on:click={() => (showModal = true)}>Show Modal</button>

<div class="modal-wrapper">
  <Modal
    bind:showModal
    on:close={() => (formState = null)}
    preventCancel={formState === 'submitting'}
  >
    <form
      method="post"
      use:enhance={async () => {
        formState = 'submitting';
        // Show the submitting state for a minimum of 1000ms.
        const timer = new Promise((resolve) => setTimeout(resolve, 1000));
        return async ({ update }) => {
          await timer;
          await update();
          await tick(); // Update the exported form object.
          formState = 'submitted';
        };
      }}
    >
      <!-- Resets the form properly by recreating the input fields. -->
      <!-- Reference https://github.com/sveltejs/svelte/issues/8220 -->
      {#if formState !== 'submitted'}
        <input type="text" name="message" size="10" value="Hello, World!" required />
        <button disabled={formState === 'submitting'}>
          {formState === 'submitting' ? 'Submitting' : 'Submit'}
        </button>
      {:else if form?.now}
        <p>Submitted at {form.now.toISOString()}</p>
      {/if}
      <button
        type="button"
        disabled={formState === 'submitting'}
        on:click={() => (showModal = false)}
      >
        Close
      </button>
    </form>
  </Modal>
</div>

<style>
  .modal-wrapper > :global(dialog) {
    width: 20rem;
    border-radius: 0.375rem;
    padding: 1rem;
  }
  .modal-wrapper > :global(dialog::backdrop) {
    backdrop-filter: blur(8px) brightness(0.5);
  }
</style>
export const actions = {
  default: async () => {
    await new Promise((resolve) => setTimeout(resolve, Math.floor(Math.random()) * 5000));
    return { now: new Date() };
  }
};