Table of Contents
The Problem
You’re debugging a Vue component where clicking a button should toggle a panel’s visibility, but nothing happens. The button renders, the click handler fires, but the panel stays hidden (or visible). Where’s the disconnect?
The Debug Checklist
When Vue show/hide logic breaks, check these four spots in order:
1. The State Variable Name
Is your state variable named consistently? Check your data() function:
data() {
return {
showAdvanced: false // ← Is this the exact name you're using everywhere?
}
}
Common mistake: defining showAdvanced but using show_advanced in the template.
2. The Directive Reference
Does your v-show or v-if reference the correct variable?
<div v-show="showAdvanced" class="advanced-panel">
<!-- content -->
</div>
Check for typos, wrong case (camelCase vs snake_case), or accidentally referencing a different variable.
3. The Toggle Handler
Is the button actually changing the state?
<button @click="showAdvanced = !showAdvanced">
Advanced Options
<i :class="showAdvanced ? 'fa-angle-up' : 'fa-angle-down'"></i>
</button>
Use Vue DevTools to watch the state change in real-time. If the state toggles but the UI doesn’t update, you might have a reactivity issue.
4. Parent-Child State Sharing
If your toggle button is in one component and the panel is in another, are they sharing state correctly?
Bad: Each component has its own local copy of showAdvanced
Good: Use props down, $emit up, or shared state (Vuex/Pinia)
Full Working Example
<template>
<div>
<button @click="showAdvanced = !showAdvanced" class="btn btn-secondary">
{{ showAdvanced ? 'Hide' : 'Show' }} Advanced Options
<i :class="showAdvanced ? 'fa-angle-up' : 'fa-angle-down'"></i>
</button>
<transition name="fade">
<div v-show="showAdvanced" class="advanced-panel mt-3">
<!-- Your advanced options here -->
<div class="form-group">
<label>Advanced Setting 1</label>
<input type="text" class="form-control">
</div>
<div class="form-group">
<label>Advanced Setting 2</label>
<input type="text" class="form-control">
</div>
</div>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
showAdvanced: false
}
}
}
</script>
<style scoped>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
Why This Pattern Works
- Single source of truth: One state variable controls everything
- Clear naming:
showAdvancedis unambiguous - Tight coupling: Button and panel reference the same variable
- Visual feedback: Icon changes to reflect state
Pro Tip: Use Vue DevTools
Install the Vue DevTools browser extension and watch your component’s state in real-time. When you click the button, you should see showAdvanced flip from false to true. If it doesn’t, your click handler isn’t working. If it does but the UI doesn’t update, you have a reactivity problem.
Next time your Vue show/hide logic breaks, work through this checklist. Nine times out of ten, it’s a variable name mismatch or a missing reactivity binding.
Leave a Reply