Debugging Vue Component Show/Hide State

📖 3 minutes read

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: showAdvanced is 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.

Daryle De Silva

VP of Technology

11+ years building and scaling web applications. Writing about what I learn in the trenches.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *