Search code examples
javascriptvue.jsvuejs2conditional-rendering

VueJs - Dropdown list


Hello I'm doing a dropdown in my website and I'm really new in Vue. I'm using conditional rendering for display some cards. Something like: Cars, Motos, Bikes. When i click on Cars there is a dropdown and i get a list of cars, same on others.

                        <h2 class="text-center my-font text-light"><button v-on:click="toggle = !toggle" class="badge badge-danger menu-label-size w-50">Cars</button></h2> 
                        <div v-if="toggle" class="row">
                          <div class="col-12">
                            <div class="cards-item text-center ">
                              <div v-for="item in cars" ::key="item.id" class="card" style="width: 10rem;">
                                  <img :src="'./images/cars/img' + item.img + '.png'" class="card-img-top img-fluid" alt="item.name">
                                  <div class="card-body d-flex flex-column justify-content-end">
                                    <h4 class="card-title my-font">{{ item.name }}</h4>
                                    <p class="badge-danger font-weight-bold">{{ item.price }}</p>
                                  </div>
                                </div>
                            </div>
                          </div>
                        </div>

                        <h2 class="text-center my-font text-light"><button v-on:click="toggle = !toggle" class="badge badge-danger menu-label-size w-50">Motos</button></h2> 
                        <div v-if="toggle" class="row">
                          <div class="col-12">
                            <div class="cards-item text-center">
                              <div v-for="item in motos" ::key="item.id" class="card" style="width: 10rem;">
                                  <img :src="'./images/motos/img' + item.img + '.png'" class="card-img-top img-fluid" alt="item.name">
                                  <div class="card-body d-flex flex-column justify-content-end">
                                    <h4 class="card-title my-font">{{ item.name }}</h4>
                                    <p class="badge-danger font-weight-bold">{{ item.price }}</p>
                                  </div>
                                </div>
                            </div>
                          </div>
                        </div>

                        <h2 class="text-center my-font text-light"><button v-on:click="toggle = !toggle" class="badge badge-danger menu-label-size w-50">Bikes</button></h2> 
                        <div v-if="toggle" class="row">
                          <div class="col-12">
                            <div class="cards-item text-center">
                              <div v-for="item in bikes" ::key="item.id" class="card" style="width: 10rem;">
                                  <img :src="'./images/bikes/img' + item.img + '.png'" class="card-img-top img-fluid" alt="item.name">
                                  <div class="card-body d-flex flex-column justify-content-end">
                                    <h4 class="card-title my-font">{{ item.name }}</h4>
                                    <p class="badge-danger font-weight-bold">{{ item.price }}</p>
                                  </div>
                                </div>
                              </div>
                            </div>
                          </div>

My script:

const app = new Vue({
el: '#app',
data: {
    show: false,
    cars: [{data}],
    motos: [{data}],
    bikes: [{data}],
},
})

But when i click on Motos it only closes Cars. How to make it dynamic? Like if i press Motos then it opens and Cars closes, same for Bikes


Solution

  • You can merge your vehicles data in mounted hook, then loop thru items:

    const app = new Vue({
      el: '#demo',
      data: () => ({
        items: [],
        expanded: null,
        cars: [{img: '', name: 'car1', price: 5}, {img: '', name: 'car2', price: 6}, {img: '', name: 'car3', price: 8}],
        motors: [{img: '', name: 'motor1', price: 5}, {img: '', name: 'motor2', price: 6}, {img: '', name: 'motor3', price: 8}],
        bikes: [{img: '', name: 'bike1', price: 5}, {img: '', name: 'bike2', price: 6}, {img: '', name: 'bike3', price: 8}]
      }),
      methods: {
        expand(idx) {
          this.expanded = this.expanded === idx ?  null : idx
        }
      },
      mounted() {
        const car = {title: 'Cars', products: this.cars}
        const motor = {title: 'Motors', products: this.motors}
        const bike = {title: 'Bikes', products: this.bikes}
        this.items = [car, motor, bike]
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
    <div id="demo" class="d-flex">
      <div v-for="(group, index) in items" :key="index">
        <h2 class="text-center my-font text-light">
          <button @click="expand(group)" class="badge badge-danger menu-label-">{{ group.title }}</button>
        </h2>
        <div class="row">
          <div class="col-12">
            <div class="cards-item text-center">
              <div v-if="expanded === group">
                <div v-for="(item, idx) in group.products" :key="idx" class="card" style="width: 10rem;">
                  <img :src="'./images/motos/img' + item.img + '.png'" class="card-img-top img-fluid" :alt="item.name">
                  <div class="card-body d-flex flex-column justify-content-end">
                    <h4 class="card-title my-font">{{ item.name }}</h4>
                    <p class="badge-danger font-weight-bold">{{ item.price }}</p>
                  </div>
                </div>
               </div>
            </div>
          </div>
        </div>
      </div>
    </div>