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>