Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

stefkay's avatar

Toggle Class for an item Vue.js

So I have a list of data brought in using vue resource from an api. I'm trying to integrate this list with bootstrap accordion.

So:

I have set this :

data: {
  taller: false
}

and

class="panel panel-default" 
v-repeat="faq: faqs | filterBy searchText" 
v-transition="staggered" 
stagger="200" 
v-on="click: toggleHeight" 
v-class="active: taller">

So on click i'll call toggleHeight and pass through the faq instance :

toggleHeight: function(faq) {
  this.taller = true;
}

This function sets to taller to true however it sets it to true for all faq items, not just the one i've passed to toggle height.

How can I only return taller: true for clicked faq item?

Thanks

0 likes
5 replies
alenabdula's avatar

Well you're changing the data object and each item is dependant on that value (two-way data binding), your returned data object could be responsible for handling states, meaning you object would look like:

var demo = new Vue({
  el: '#list',
  data: {
    title: 'list',
    items: [
      {
        taller: false,
        bar: 'Foo'
      },
      {
        taller: false,
        bar: 'Baz'
      }
    ]
  }
});

But I think that's too excessive, you could simply toggle a class, do a transition via CSS.

stefkay's avatar

I thought about that also but decided against it. Problem i've got is i'm using a fixed height for the stagger element, which means that any open accordion simply doesn't show. I was hoping to add a class to the element to override the fixed height.

stefkay's avatar
stefkay
OP
Best Answer
Level 2

Hey,

Just thought i'd post a solution i've got working. So Html :

<div id="demo">

        <div class="input-group">
            <input class="form-control" v-model="searchText">
        </div>

        <script id="item-template" type="x-template">

            <div 
            class="stag"
            v-on="click: toggleHeight()"
            v-class="active: taller"
            >

                <h3>{{  item.question }}</h3>

                <h4>{{  item.answer }}</h4>

            </div>

        </script>

        <question 
            v-repeat="item: items | filterBy searchText" 
            v-transition="staggered" 
            stagger="200">
        </question>

    </div>

and the JS is :

Vue.component('question', {

        template: document.querySelector('#item-template'),

        data: function() {

            return {

                taller: false

            }

        },

        methods: {

            toggleHeight: function() {

                this.taller = ! this.taller

            }
        }

    });

    new Vue({

        el: '#demo',

        ready: function() {

            this.fetchItems();

        },

        methods: {

            fetchItems: function() {

                this.$http.get('/dev/frequently-asked-questions/api/index', function(items) {
                    this.$set('items', items);
                });

            }

        }

    })

Had to make use of components so I could target individual list items more effectively.

4 likes

Please or to participate in this conversation.