Svelte/SvelteKit «до: события»?

У меня есть пользовательский компонент Form.svelte, у которого есть собственный обработчик отправки, однако я хотел бы несколько раскрыть его, чтобы позволить мне запустить определенную функцию до вызова функции отправки.

Упрощенная версия:

Form.svelte

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

<form on:submit = {handleSubmit} class = "new-form">
   <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>

Возможно ли это, и если да, то как это реализовать?

🤔 А знаете ли вы, что...
JavaScript - это скриптовый язык программирования, разработанный Netscape Communications Corporation.


2
73
2

Ответы:

Решено

Вы можете создать диспетчер событий и создать свое собственное событие, например, с именем beforeSubmit и дайте ему обработчик с on:beforeSubmit, где вы используете компонент:

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

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

    // Do things
  }
</script>

<form on:submit = {handleSubmit} class = "new-form">
   <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>

Ответ Толле показывает, как это сделать правильно (и рекомендуется) в соответствии со стройным способом. Но так как я опоздал и уже начал писать ответ, то предложу как вариант альтернативный метод:

можно было бы передать функцию beforeSubmit в качестве аргумента компоненту формы. Это позволило бы таким образом, как показано ниже, сделать выполнение handleSubmit зависимым от результата выполнения beforeSubmit

<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} class = "new-form">
   <slot />
</form>