Home > Software engineering >  Svelte / SvelteKit 'before:event'?
Svelte / SvelteKit 'before:event'?

Time:01-13

I have a custom Form.svelte component, which has its own submit handler, however I would like to expose this somewhat, to allow me to have a specific function run before the submit function is called.

A simplified version:

Form.svelte

<script>
const handleSubmit = async () => {
  // Do things
}
</script>

<form on:submit={handleSubmit} >
   <slot />
</form>

customers/new/ page.svelte

<script lang="ts">
type Customer = { postcode: string, shipping_postcode: string };

let duplicateAddress = false;
const customer = { postcode: "", shipping_postcode: "" };

const beforeSubmit = () => {
  if (duplicateAddress) customer.shipping_postcode = customer.postcode;

  if (!customer.postcode) {
     // Throw an error, for example.
  }
}
</script>

<Form before:submit={beforeSubmit} data={customer}>
  <input type="text" bind:value={customer.postcode} placeholder="Postcode" />
  <input type="checkbox" bind:checked={duplicateAddress} />
</Form>

Is this possible and, if so, how do I implement this?

CodePudding user response:

You could create an event dispatcher and emit your own event called e.g. beforeSubmit and give it a handler with on:beforeSubmit where you use the component:

<!-- Form.svelte -->
<script>
  import { createEventDispatcher } from 'svelte';

  const dispatch = createEventDispatcher();
    
  const handleSubmit = async () => {
    dispatch('beforeSubmit');

    // Do things
  }
</script>

<form on:submit={handleSubmit} >
   <slot />
</form>

<!-- customers/new/ page.svelte -->
<script lang="ts">
  // ...

  const beforeSubmit = () => {
    // ...
  }
</script>

<Form on:beforeSubmit={beforeSubmit} data={customer}>
  <input type="text" bind:value={customer.postcode} placeholder="Postcode" />
  <input type="checkbox" bind:checked={duplicateAddress} />
</Form>

CodePudding user response:

Tholle's answer shows how to do it correctly (and recommended) according to svelte way. But because of I was late and I have already started writing an answer, I will offer an alternative method as an option:

it would be possible to pass the beforeSubmit function as an argument to the Form component. This would allow in such a way as shown below, to make the execution of handleSubmit dependent on the result of the beforeSubmit execution

<script lang="ts">

import Form from './Form.svelte';
    

let duplicateAddress = false;
const customer = { postcode: "", shipping_postcode: "" };

const beforeSubmit = (e) => {   
  if (duplicateAddress) customer.shipping_postcode = customer.postcode;

    e.preventDefault()
  if (!customer.postcode) {
     // Throw an error, for example.
        alert('cancel')
        return false;
  }
    
    return true;
}
</script>

<Form data={customer} beforeSubmit={beforeSubmit}>
  <input type="text" bind:value={customer.postcode} placeholder="Postcode" />
  <input type="checkbox" bind:checked={duplicateAddress} />
</Form>
<script>
    
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
    
export let beforeSubmit = null;
    
const handleSubmit = async (e) => {
    
    alert('submit')
}
</script>

<form on:submit={beforeSubmit ? e => beforeSubmit(e) && handleSubmit(e) : handleSubmit} >
   <slot />
</form>
  • Related