Chapter 77: Vue v-else Directive
V-else
This directive has no argument, no condition, no value — it simply means:
“If none of the previous v-if or v-else-if conditions were true → render this block.”
It is the default fallback case — exactly like the else block in JavaScript.
1. The Golden Rules of v-else (Memorize These Forever)
-
v-else must come immediately after a v-if or v-else-if block → There can be nothing between them (no text, no other element, no comment)
Wrong:
HTML012345678<div v-if="isAdmin">Admin panel</div><p>Some random text</p> <!-- ← breaks the chain --><div v-else>Guest view</div>Correct:
HTML01234567<div v-if="isAdmin">Admin panel</div><div v-else>Guest view</div> -
You can only have one v-else per v-if chain → It has to be the very last block
-
It can be used on <template> tags (so you can conditionally render multiple elements without an extra wrapper <div>)
-
It works perfectly with <Transition> for enter/leave animations
2. Real, Practical Example – User Role Dashboard
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
<template> <div class="dashboard"> <h1>Dashboard</h1> <!-- First condition – highest privilege --> <div v-if="user.role === 'admin'" class="admin-panel"> <h2>Admin Controls</h2> <button>Manage Users</button> <button>Delete Database</button> <p>Full access granted</p> </div> <!-- Second condition – only checked if not admin --> <div v-else-if="user.role === 'editor'" class="editor-panel"> <h2>Editor Tools</h2> <button>Create Post</button> <button>Edit Posts</button> <p>Content creation allowed</p> </div> <!-- Third condition – only checked if not admin or editor --> <div v-else-if="user.role === 'viewer'" class="viewer-panel"> <h2>Read-Only View</h2> <p>You can view content but cannot edit</p> </div> <!-- Default fallback – when role is unknown / not logged in --> <div v-else class="guest-panel"> <h2>Please Sign In</h2> <p>You need to log in to access the dashboard.</p> <button @click="goToLogin">Login</button> </div> <!-- Status line – always visible --> <p class="status">Current role: {{ user.role || 'Guest' }}</p> </div> </template> <script setup lang="ts"> import { reactive } from 'vue' const user = reactive({ role: 'editor' // change this value to see different panels }) function goToLogin() { alert('Redirecting to login page...') // router.push('/login') in real app } </script> <style scoped> .dashboard { max-width: 700px; margin: 3rem auto; padding: 2rem; background: white; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.08); } .admin-panel { background: #eff6ff; padding: 2rem; border-radius: 12px; border: 2px solid #3b82f6; } .editor-panel { background: #f0fdf4; padding: 2rem; border-radius: 12px; border: 2px solid #22c55e; } .viewer-panel { background: #f3f4f6; padding: 2rem; border-radius: 12px; border: 2px solid #6b7280; } .guest-panel { background: #fefce8; padding: 2rem; border-radius: 12px; border: 2px solid #ca8a04; } .status { margin-top: 2rem; text-align: center; color: #4b5563; font-style: italic; } button { padding: 0.8rem 1.5rem; background: #3b82f6; color: white; border: none; border-radius: 6px; cursor: pointer; margin-top: 1rem; } </style> |
4. Very Common Pattern – Using <template> with v-else-if / v-else
When you want to conditionally render multiple elements without adding an extra wrapper <div> (keeps DOM clean):
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<template> <div class="page"> <header>Header always visible</header> <template v-if="user.role === 'admin'"> <nav>Admin Navigation</nav> <aside>Admin Sidebar</aside> <main>Admin Content</main> </template> <template v-else-if="user.role === 'user'"> <nav>User Navigation</nav> <main>User Content</main> </template> <template v-else> <div class="login-prompt"> <h2>Please log in</h2> <button>Sign In</button> </div> </template> <footer>Footer always visible</footer> </div> </template> |
→ When role !== ‘admin’ → no <nav> or <aside> is rendered — zero extra DOM nodes
5. Combining v-if / v-else-if with <Transition>
|
0 1 2 3 4 5 6 7 8 9 10 |
<Transition name="fade"> <div v-if="status === 'success'" class="success">Success!</div> <div v-else-if="status === 'error'" class="error">Error occurred</div> <div v-else class="unknown">Waiting...</div> </Transition> |
→ All three states fade in/out smoothly when status changes
Quick Summary Table – v-if Family (2026 Must-Know)
| Directive | When to use it | DOM presence when false | Re-mounts on true? | Cost on toggle | Animation support |
|---|---|---|---|---|---|
| v-if | First condition, rarely changes | Removed | Yes | Higher | Perfect with <Transition> |
| v-else-if | Additional conditions in chain | Removed | Yes | Higher | Yes |
| v-else | Default fallback – no condition | Removed | Yes | Higher | Yes |
| v-show | Frequent toggles, light content | Hidden (display:none) | No | Very low | Works, but element always exists |
Pro Tips from Real Projects (Hyderabad 2026)
- Use v-if / v-else-if / v-else chains for status indicators, auth/role panels, payment results, form steps
- Use <template v-else-if> when you need to conditionally render multiple elements without extra wrapper div
- Prefer v-show for very frequent toggles (tabs, accordions, loading spinners)
- Combine v-if + <Transition> for beautiful enter/leave animations
- Never put very expensive components behind v-else-if if the condition changes often — use v-show instead
- For accessibility → use aria-live=”polite” on containers that change via v-if
Your mini practice task:
- Create a payment status card with v-if / v-else-if / v-else chain
- Use <template> for each branch so no extra wrapper divs
- Add different icons/colors/buttons for each state
- Wrap the whole block with <Transition name=”fade”> → see smooth state changes
Any part confusing? Want full examples for:
- v-if + <Transition> + modal animation?
- v-if vs v-show performance comparison?
- v-if inside <TransitionGroup> for list items?
- Real auth guard with v-if + router?
Just tell me — we’ll build the next clean conditional UI together 🚀
