Implementing Expand/Collapse List Items with Vue.js

To create an exapndable list where clicking an item shows its content while hiding others, implement a Vue component with state management for tracking active items and toggle status.

Template Structure

<div class="faq-section">
    <h3>Frequently Asked Questions</h3>
    <ul class="faq-list">
        <div v-for="(question, idx) in questions" 
             :class="{'active-item': activeIndex === idx}">
            <li @click="toggleQuestion(question.id, idx)">
                <span class="question-title">{{ question.title }}</span>
                <span class="toggle-icon">{{ activeIndex === idx ? '−' : '+' }}</span>
            </li>
            <div class="answer-content" v-if="activeIndex === idx">
                <p v-for="(answer, ansIdx) in currentAnswers" 
                   :key="ansIdx">
                    {{ ansIdx + 1 }}. {{ answer.content }}
                </p>
            </div>
        </div>
    </ul>
</div>

Component Logic

export default {
    data() {
        return {
            activeIndex: -1,
            toggleFlag: false,
            clickHistory: [],
            currentAnswers: []
        }
    },
    methods: {
        toggleQuestion(qId, idx) {
            this.clickHistory.push(idx);
            
            const lastClick = this.clickHistory[this.clickHistory.length - 1];
            const previousClick = this.clickHistory[this.clickHistory.length - 2];
            
            if (lastClick === previousClick && this.toggleFlag) {
                this.activeIndex = -1;
            } else {
                this.activeIndex = idx;
                this.fetchAnswers(qId);
            }
            
            this.toggleFlag = !this.toggleFlag;
        },
        
        fetchAnswers(questionId) {
            const requestData = { 
                parentId: this.parentId, 
                questionType: questionId 
            };
            
            getQuestionAnswers(requestData).then(response => {
                this.currentAnswers = response.data;
            });
        }
    }
}

CSS Styling

.active-item {
    background-color: #f5f5f5;
    border-left: 3px solid #007bff;
}

.question-title {
    font-weight: bold;
    color: #333;
}

.toggle-icon {
    float: right;
    font-weight: bold;
    color: #666;
}

.answer-content {
    padding: 10px;
    background-color: #fff;
    border-top: 1px solid #eee;
}

The component tracks the active item index and toggle state. When a user clicks a list item, it checks if the same item was clicked consecutive with the toggle flag active, collapsing the content if both conditions are met. Otherwise, it expands the clicked item and fetches related data.

Tags: Vue.js List Management Toggle Functionality State Management UI Components

Posted on Sun, 10 May 2026 13:14:52 +0000 by Firestorm3d