Home > Software design >  Vue3 can't get dynamic styling to only apply to specific buttons
Vue3 can't get dynamic styling to only apply to specific buttons

Time:11-13

I am in the process of learning vue and I'm stumped on how to get these buttons to dynamically style separately when clicked. These are filters for a list of products and I would like the apply one style when the filter is 'on' and a different style when the filter is 'off'. I can get the styles to update dynamically, but all of the buttons change style when any of them are clicked. The actual filter functionality is working as expected (the products are being filtered out when the button for that product is clicked).

In the code snippet, mode is passed to the BaseButton component, which is then applied as the class.

<template>
    <ul>
        <li v-for="genus of genusList" :key="genus.label">
            <BaseButton @click="filterGenus(genus.label)"  :mode="genusClicked.clicked ? 'outline' :''">
                {{ genus.label }}
            </BaseButton>
        </li>
        <BaseButton @click="clearFilter()" mode="flat">Clear Filter</BaseButton>
    </ul>
    </template>



    methods: {
        filterGenus(selectedGenus) {
            this.clickedGenus = selectedGenus
            this.clicked = !this.clicked
            this.$emit('filter-genus', selectedGenus)
        },
        clearFilter() {
            this.$emit('clear-filter')
        }
    },

I have tried making a computed value to add a .clicked value to the genusList object but that didn't seem to help.

CodePudding user response:

Maybe something like following snippet (if you need more buttons to be styled at once save selected in array, if only one just save selected):

const app = Vue.createApp({
  data() {
    return {
      genusList: [{label: 1}, {label: 2}, {label: 3}],
      selGenus: [],
    };
  },
  methods: {
    isSelected(selectedGenus) {
      return this.selGenus.includes(selectedGenus)
    },
    filterGenus(selectedGenus) {
      if (this.isSelected(selectedGenus)) {
        this.selGenus = this.selGenus.filter(s => s !== selectedGenus)
      } else {
        this.selGenus = [...this.selGenus, selectedGenus]
      }
      this.$emit('filter-genus', selectedGenus)
    },
    clearFilter() {
      this.selGenus = []
      this.$emit('clear-filter')
    }
  },
})
app.component('baseButton', {
  template: `<button :><slot /></button>`,
  props: ['mode']
})
app.mount('#demo')
.outline {
  outline: 2px solid red;
}
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="demo">
  <ul>
    <li v-for="genus of genusList" :key="genus.label">
      <base-button @click="filterGenus(genus.label)" 
                   :mode="isSelected(genus.label) ? 'outline' :''">
        {{ genus.label }}
      </base-button>
    </li>
    <base-button @click="clearFilter()" mode="flat">
      Clear Filter
    </base-button>
  </ul>
</div>

  • Related