Capture the Submission

The booking form collects data and shows a preview. Now we need to handle what happens when users click “Request Booking.” In this lesson, you’ll intercept the submit event and process the form data.


What You’ll Learn

  • Handle form submit events
  • Prevent default browser behavior
  • Show confirmation after submission
  • Track submission state

The Problem : Default Behavior

By default, when a form is submitted, the browser performs a full page refresh and sends the form data to the server. In our case, we don’t want that.

We want to:

  1. Prevent the page refresh
  2. Process the data ourselves
  3. Show a confirmation message

Add the Submit Handler

Add a submitted state variable and a submit handler function:

<!-- filename: src/lib/components/BookingForm.svelte -->
<script>
	// ... existing code  ..

	let submitted = $state(false)

	// Add Format date and time functions...

	/**
	 * @param {{ preventDefault: () => void; }} event
	 */
	function handleSubmit(event) {
		event.preventDefault()

		// For now, just log the data and show confirmation
		console.log('Booking submitted:', {
			customerName,
			email,
			date,
			time,
			notes
		})

		submitted = true
	}
</script>

Understanding the Submit Handler

The handleSubmit function is called when the form is submitted. Here’s what each part does:

The Event Parameter: The event parameter is a SubmitEvent object that the browser automatically passes to the handler. It contains information about the form submission, including which form was submitted and how (button click or Enter key).

Preventing Default Behavior: The event.preventDefault() method stops the browser’s default form submission. Without this, the browser would:

  1. Collect the form data
  2. Send an HTTP POST request to the current URL
  3. Refresh the entire page
  4. Lose all client-side state

By calling preventDefault(), we take full control and handle everything in JavaScript.

Logging for Debugging: The console.log() statement is helpful during development. It lets you verify that:

  • The handler is being called
  • The state variables contain the expected values
  • The data structure is correct

Open your browser’s Developer Tools (F12 or Cmd+Option+I) to see the logged output.

Svelte offers better ways for debugging and we will cover those later, but console.log is simple and effective for now.

Setting Submission State: After preventing the default and logging the data, we set submitted = true. This boolean flag triggers the UI to switch from the form view to the confirmation view. Because submitted is declared with $state(), changing it automatically updates any part of the template that references it.


Connect the Handler to the Form

Add the onsubmit handler to the form element:

<form onsubmit={handleSubmit}>
	<!-- ... form fields ... -->
</form>

Now clicking “Request Booking” (or pressing Enter in a field) will:

  1. Prevent page refresh
  2. Log the booking data to console
  3. Set submitted to true

Show Confirmation

Common practice after submiting any form is to show a confirmation message, send email notifications, or redirect the user. In our form we render a confirmation block on successful submission.

To do this, first, we need to conditionally render either the form or the confirmation message based on the submitted state. We will use an {#if} and {:else} block. With this, we can show different content depending on whether the form has been submitted.

<!-- filename: src/lib/components/BookingForm.svelte -->

<script>
  // ... existing code  ..
</script>

<div class="booking-container">
	<!-- add if - else -->
	{#if submitted}
		<div class="confirmation">
			<h2>Booking Requested!</h2>
			<p>Thank you, {customerName}. We've received your booking request.</p>

			<dl>
				<dt>Service Date</dt>
				<dd>{formatDate(date)} at {formatTime(time)}</dd>

				<dt>Confirmation Email</dt>
				<dd>We'll send details to {email}</dd>
			</dl>

			<p>We'll contact you within 24 hours to confirm your appointment.</p>
		</div>
	{:else}
		<form onsubmit={handleSubmit}>
			<!-- ... form fields ... -->
		</form>

		<aside class="preview">
			<!-- ... preview content ... -->
		</aside>
	{/if}
</div>

What happens here:

When the user clicks “Submit” the handleSubmit function runs and sets submitted to true. This causes Svelte to re-evaluate the {#if} block:

  • If submitted is true, the confirmation message is displayed, showing the user’s name, selected date and time, and email.
  • If submitted is false, the {:else} block renders the booking form and live preview as before.

The Complete Component

Here’s the full BookingForm.svelte with submit handling:

<!-- filename: src/lib/components/BookingForm.svelte -->
<script>
	let customerName = $state('')
	let email = $state('')
	let date = $state('')
	let time = $state('')
	let notes = $state('')

	let submitted = $state(false)

	function formatDate(dateString) {
		if (!dateString) return 'Not selected'
		const dateObj = new Date(dateString + 'T00:00:00')
		return dateObj.toLocaleDateString('en-US', {
			weekday: 'long',
			year: 'numeric',
			month: 'long',
			day: 'numeric'
		})
	}

	function formatTime(timeString) {
		if (!timeString) return 'Not selected'
		const [hours, minutes] = timeString.split(':')
		const hour = parseInt(hours)
		const ampm = hour >= 12 ? 'PM' : 'AM'
		const displayHour = hour % 12 || 12
		return `${displayHour}:${minutes} ${ampm}`
	}

	function handleSubmit(event) {
		event.preventDefault()

		console.log('Booking submitted:', {
			customerName,
			email,
			date,
			time,
			notes
		})

		submitted = true
	}
</script>

<div class="booking-container">
	{#if submitted}
		<div class="confirmation">
			<h2>Booking Requested!</h2>
			<p>Thank you, {customerName}. We've received your booking request.</p>

			<dl>
				<dt>Service Date</dt>
				<dd>{formatDate(date)} at {formatTime(time)}</dd>

				<dt>Confirmation Email</dt>
				<dd>We'll send details to {email}</dd>
			</dl>

			<p>We'll contact you within 24 hours to confirm your appointment.</p>
		</div>
	{:else}
		<form onsubmit={handleSubmit}>
			<h2>Book a Service</h2>

			<div class="field">
				<label for="name">Your Name</label>
				<input
					type="text"
					id="name"
					name="name"
					placeholder="Jane Smith"
					bind:value={customerName}
					required
				/>
			</div>

			<div class="field">
				<label for="email">Email Address</label>
				<input
					type="email"
					id="email"
					name="email"
					placeholder="jane@example.com"
					bind:value={email}
					required
				/>
			</div>

			<div class="field">
				<label for="date">Preferred Date</label>
				<input type="date" id="date" name="date" bind:value={date} required />
			</div>

			<div class="field">
				<label for="time">Preferred Time</label>
				<select id="time" name="time" bind:value={time} required>
					<option value="">Select a time...</option>
					<option value="09:00">9:00 AM</option>
					<option value="10:00">10:00 AM</option>
					<option value="11:00">11:00 AM</option>
					<option value="13:00">1:00 PM</option>
					<option value="14:00">2:00 PM</option>
					<option value="15:00">3:00 PM</option>
				</select>
			</div>

			<div class="field">
				<label for="notes">Additional Notes</label>
				<textarea
					id="notes"
					name="notes"
					rows="3"
					placeholder="Any special requests?"
					bind:value={notes}
				></textarea>
			</div>

			<button type="submit">Request Booking</button>
		</form>

		<aside class="preview">
			<h3>Booking Preview</h3>

			<dl>
				<dt>Name</dt>
				<dd>{customerName || 'Not entered'}</dd>

				<dt>Email</dt>
				<dd>{email || 'Not entered'}</dd>

				<dt>Date</dt>
				<dd>{formatDate(date)}</dd>

				<dt>Time</dt>
				<dd>{formatTime(time)}</dd>

				<dt>Notes</dt>
				<dd>{notes || 'None'}</dd>
			</dl>
		</aside>
	{/if}
</div>

Notice we also added required to the essential fields. The browser will validate these before allowing submission.


Test the Flow

  1. Visit a service page
  2. Fill out all required fields
  3. Click “Request Booking”
  4. See the confirmation message with your details
  5. Check the browser console — your booking data is logged

What’s Not Happening Yet

This is client-side only. The booking:

  • Isn’t saved to a database
  • Doesn’t send an email
  • Disappears if you refresh the page

Real persistence requires server-side handling, which we’ll cover in Module 12: Forms & Actions. For now, we’re focused on the client-side experience.


Common Mistakes

Forgetting event.preventDefault()

<!-- ❌ Page will refresh -->
function handleSubmit(event) {
  console.log('Submitted!');
  submitted = true;
}

<!-- ✅ Prevents refresh -->
function handleSubmit(event) {
  event.preventDefault();
  console.log('Submitted!');
  submitted = true;
}

Without preventDefault(), the browser takes over and refreshes the page.

Using onclick on a Submit Button

<!-- ❌ Doesn't capture Enter key submissions -->
<button type="submit" onclick={handleSubmit}>Submit</button>

<!-- ✅ Captures all form submissions -->
<form onsubmit={handleSubmit}>
	<button type="submit">Submit</button>
</form>

Always handle submit on the <form> element, not click on the button. This ensures keyboard submissions (pressing Enter) also work.


Summary

The booking form now handles submissions. It prevents the default page refresh, processes the form data, and shows a confirmation message. The data isn’t persisted yet, but the client-side flow is complete.

Key takeaways:

  • Use onsubmit on the form, not onclick on the button
  • Call event.preventDefault() to stop default browser behavior
  • Use state to toggle between form and confirmation views

Next Steps

Users can submit once, but what if they want to book another service? Continue with Reset Form After “Submission” to add a “Book Another” feature.