Show It or Hide It
Not everything should display all the time. Error messages appear when something goes wrong. Loading spinners show while data fetches. Success confirmations appear after form submission. Svelte’s conditional blocks let you control what renders based on your application’s state.
What You’ll Learn
- Use
{#if}to conditionally render content - Add
{:else}for alternative content - Chain multiple conditions with
{:else if} - Apply conditionals to BookIt’s booking form
The Basic If Block
The {#if} syntax mirrors JavaScript’s if statement:
{#if condition}
<p>This renders when condition is true</p>
{/if} The content inside only appears when condition is truthy. When the condition is falsy, nothing renders in that spot.
A Practical Example
Let’s see how conditions work with reactive state. This example shows a welcome message based on login state:
<script>
let isLoggedIn = $state(false);
</script>
{#if isLoggedIn}
<p>Welcome back!</p>
{/if}
<button onclick={() => isLoggedIn = !isLoggedIn}>
Toggle Login
</button> Click the button. The welcome message appears and disappears. The {#if} block reacts to state changes automatically — no manual DOM manipulation needed.
Note: This is a learning example to demonstrate the concept. We’re not adding this to BookIt.
Conditions Can Be Any Expression
The condition doesn’t have to be a simple boolean. Any JavaScript expression works:
<script>
let services = $state([]);
let searchQuery = $state('');
let user = $state(null);
let price = $state(50);
</script>
<!-- Array length check -->
{#if services.length > 0}
<p>Found {services.length} services</p>
{/if}
<!-- String check -->
{#if searchQuery}
<p>Searching for: {searchQuery}</p>
{/if}
<!-- Null check -->
{#if user}
<p>Hello, {user.name}</p>
{/if}
<!-- Comparison -->
{#if price > 100}
<span class="premium">Premium Service</span>
{/if} JavaScript’s truthy/falsy rules apply. These values are falsy (block doesn’t render): 0, "", null, undefined, false. Everything else is truthy.
Adding an Else Branch
Often you want to show alternative content when the condition is false:
{#if isLoggedIn}
<p>Welcome back!</p>
{:else}
<p>Please log in to continue.</p>
{/if} Now something always displays — either the welcome message or the login prompt. Notice the syntax: {:else} uses a colon, indicating a continuation of the block rather than a new block.
Multiple Conditions with {:else if}
Sometimes you need more than two options. Status might be pending, confirmed, completed, or cancelled. The {:else if} block handles these scenarios:
{#if status === 'pending'}
<span class="badge pending">⏳ Pending</span>
{:else if status === 'confirmed'}
<span class="badge confirmed">✓ Confirmed</span>
{:else if status === 'completed'}
<span class="badge completed">✓ Completed</span>
{:else if status === 'cancelled'}
<span class="badge cancelled">✗ Cancelled</span>
{:else}
<span class="badge">Unknown</span>
{/if} Svelte checks conditions from top to bottom. The first true condition wins, and the rest are skipped. We’ll use this exact pattern later when we build the bookings management page.
Order Matters
Conditions are evaluated top-to-bottom. The first match wins:
<script>
let price = $state(75);
</script>
<!-- ❌ Wrong order — "Premium" never triggers -->
{#if price > 0}
<span>Budget</span>
{:else if price > 50}
<span>Standard</span>
{:else if price > 100}
<span>Premium</span>
{/if}
<!-- ✅ Correct order — most specific first -->
{#if price > 100}
<span>Premium</span>
{:else if price > 50}
<span>Standard</span>
{:else if price > 0}
<span>Budget</span>
{/if} Put the most specific (restrictive) conditions first.
Applying to BookIt: Form Confirmation
Now let’s apply what we learned to BookIt. We’ll update the booking form to show a confirmation message after submission. Before submission, users see the form. After submission, they see a thank-you message.
Open your BookingForm.svelte and update it with this pattern:
<!-- 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 handleSubmit(event) {
event.preventDefault();
submitted = true;
}
</script>
{#if submitted}
<div class="confirmation">
<h2>Booking Requested!</h2>
<p>Thanks, {customerName}! We'll confirm your booking soon.</p>
<p>We'll send details to {email}.</p>
<button onclick={() => submitted = false}>Book Another Service</button>
</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}
/>
</div>
<div class="field">
<label for="email">Email Address</label>
<input
type="email"
id="email"
name="email"
placeholder="jane@example.com"
bind:value={email}
/>
</div>
<div class="field">
<label for="date">Preferred Date</label>
<input type="date" id="date" name="date" bind:value={date} />
</div>
<div class="field">
<label for="time">Preferred Time</label>
<select id="time" name="time" bind:value={time}>
<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>
{/if} What We Added
- A
submittedstate variable — Tracks whether the form has been submitted - A
handleSubmitfunction — Setssubmittedtotruewhen the form is submitted - An
{#if}/{:else}block — Shows confirmation when submitted, form otherwise - A “Book Another” button — Resets
submittedto show the form again
Test It
- Navigate to a service page (e.g.,
http://localhost:5173/services/lawn-mowing) - Fill in your name and email
- Click “Request Booking”
- You should see the confirmation message with your name
- Click “Book Another Service” to return to the form
One condition controls which entire view appears. This is a common pattern for multi-step flows.
Nested Conditions
You can nest {#if} blocks for complex logic:
{#if isLoggedIn}
{#if hasBookings}
<p>View your upcoming bookings</p>
{:else}
<p>You have no bookings yet</p>
{/if}
{:else}
<p>Log in to see your bookings</p>
{/if} This checks login status first, then booking status. However, deeply nested conditions become hard to read. Consider refactoring complex logic into derived values or separate components.
When Else-If Gets Unwieldy
Long else-if chains become hard to read. For many conditions, consider alternatives:
Object lookup:
<script>
const categoryDescriptions = {
'lawn-care': 'Professional lawn maintenance services.',
'tree-care': 'Tree pruning and maintenance.',
'consultation': 'Expert garden advice and planning.',
'cleaning': 'Outdoor cleaning and pressure washing.'
};
let selectedCategory = $state('lawn-care');
</script>
<p>{categoryDescriptions[selectedCategory]}</p> Data-driven rendering with $derived:
<script>
const categories = [
{ id: 'lawn-care', name: 'Lawn Care', description: '...', icon: '🌿' },
{ id: 'tree-care', name: 'Tree Care', description: '...', icon: '🌳' },
// ... more categories
];
let selectedCategory = $state('lawn-care');
let currentCategory = $derived(
categories.find(c => c.id === selectedCategory)
);
</script>
{#if currentCategory}
<h2>{currentCategory.icon} {currentCategory.name}</h2>
<p>{currentCategory.description}</p>
{/if} Rule of thumb: three conditions? Use else-if. Ten conditions? Use data structures. We’ll explore $derived more in Module 10.
Common Mistakes
Forgetting the Closing Tag
<!-- ❌ Missing closing tag -->
{#if isLoggedIn}
<p>Welcome!</p>
<!-- ✅ Properly closed -->
{#if isLoggedIn}
<p>Welcome!</p>
{/if} Every {#if} needs a matching {/if}.
Using Assignment Instead of Comparison
<!-- ❌ This assigns, doesn't compare -->
{#if count = 5}
<!-- ✅ This compares -->
{#if count === 5} Use === for comparison, not =.
Checking Array Existence vs Length
<!-- ❌ Array exists but might be empty -->
{#if services}
<p>Showing services</p>
{/if}
<!-- ✅ Check if array has items -->
{#if services.length > 0}
<p>Showing services</p>
{/if} An empty array [] is truthy. Check .length to verify it has content.
Missing Final Else
<!-- ❌ No fallback for unexpected values -->
{#if status === 'active'}
<span>Active</span>
{:else if status === 'inactive'}
<span>Inactive</span>
{/if}
<!-- ✅ Always handle unexpected cases -->
{#if status === 'active'}
<span>Active</span>
{:else if status === 'inactive'}
<span>Inactive</span>
{:else}
<span>Unknown</span>
{/if} Summary
Svelte’s conditional blocks control what renders based on state. You learned all three conditional patterns and applied them to BookIt’s booking form, creating a two-state view that switches between the form and a confirmation message.
What you built:
- Updated
BookingForm.sveltewith submission state - Added a confirmation view using
{#if}/{:else} - Created a “Book Another” button to reset the form
Key takeaways:
{#if condition}...{/if}renders content conditionally{:else}provides alternative content when condition is false{:else if}chains multiple conditions in sequence- First matching condition wins — order matters
Next Steps
What happens when there’s nothing to show? Continue with Handle Empty States to display helpful messages when the services list is empty.