How to do multi-class binding using vue.js with click event?

684 Views Asked by At

Have a healthy days. The problem I'm trying to solve is conceptually very simple. I'm new to working with Vue.js and I have some perception issues with the class binding. I am preparing a mini project to understand the subject. There are color buttons at the top and an area at the bottom that changes color when these buttons are clicked. HTML side

const app = Vue.createApp({
        data(){
          return {
            color_palette : [
              {
                index : 1,
                id : "red",
                css_class : "red-box"
              },
              {
                index : 2,
                id : "blue",
                css_class : "blue-box"
              },
              {
                index : 3,
                id : "green",
                css_class : "green-box"
              },
              {
                index : 4,
                id : "yellow",
                css_class : "yellow-box"
              }
            ],
            
          }
        },
        
        
      }).mount('#app');
.container {
  width: 100%;
  height: auto;
  padding: 10px;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
  -webkit-box-align: start;
      -ms-flex-align: start;
          align-items: start;
}

.css--class--app .css--palette {
  list-style-type: none;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
}

.css--class--app .css--palette li {
  width: 50px;
  height: 50px;
  background-color: #ccc;
  border-radius: 50%;
  margin-left: 5px;
  border: 1px solid #bbb;
}

.css--class--app .result-box {
  width: 100%;
  height: 100px;
  background-color: #18bf71;
  margin-top: 15px;
  border-radius: 5px;
  border-bottom: 1px solid #ccc;
  -webkit-transition: background-color 0.5s;
  transition: background-color 0.5s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<header>CSS Class App</header>
    <div class="container css--class--app" id="app">
      <div class="card text-center">
        <ul class="css--palette text-center">
          <li v-for="color in color_palette" ></li>
        </ul>
        <div class="result-box" ></div>
      </div>
    </div>

In such a case, what kind of click event is required to define buttons? I dont want to copy and paste the answers. I just want a explanation to understand concept of class binding with multiple click event.

1

There are 1 best solutions below

0
On BEST ANSWER

Create an activeClass property and bind it to the result box class. An important thing to notice is that you may use class and :class simultaneously. Both are applied:

<div class="result-box" :class="activeClass"></div>
data() {
  return {
    activeClass: ''
  }
}

On click, change the activeClass:

@click="activeClass = color.css_class"

Also bind the classes to the buttons. Putting it all together:

<li v-for="color in color_palette"
    :class="color.css_class"
    @click="activeClass = color.css_class"></li>

You may want to reduce the specificity of your default classes or you'll run into a little complexity when trying to give precedence to the bound class (or you can just use !important). Here's a demo:

const { createApp } = Vue;
const app = createApp({
  data(){
    return {
      activeClass: '',
      color_palette : [
        {
          index : 1,
          id : "red",
          css_class : "red-box"
        },
        {
          index : 2,
          id : "blue",
          css_class : "blue-box"
        },
        {
          index : 3,
          id : "green",
          css_class : "green-box"
        },
        {
          index : 4,
          id : "yellow",
          css_class : "yellow-box"
        }
      ],
    }
  }
});
app.mount("#app");
.container {
  width: 100%;
  height: auto;
  padding: 10px;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
  -webkit-box-align: start;
      -ms-flex-align: start;
          align-items: start;
}

.css--class--app .css--palette {
  list-style-type: none;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
}

.css--class--app .css--palette li {
  width: 50px;
  height: 50px;
  background-color: #ccc;
  border-radius: 50%;
  margin-left: 5px;
  border: 1px solid #bbb;
}

.css--class--app .result-box {
  width: 100%;
  height: 100px;
  background-color: #18bf71;
  margin-top: 15px;
  border-radius: 5px;
  border-bottom: 1px solid #ccc;
  -webkit-transition: background-color 0.5s;
  transition: background-color 0.5s;
}

.css--class--app .red-box {
  background: red !important;
}
.css--class--app .blue-box {
  background: blue !important;
}
.css--class--app .green-box {
  background: green !important;
}
.css--class--app .yellow-box {
  background: yellow !important;
}
<div id="app" class="">
  <header>CSS Class App</header>
  <div class="container css--class--app" id="app">
    <div class="card text-center">
      <ul class="css--palette text-center">
        <li v-for="color in color_palette"
            :class="color.css_class"
            @click="activeClass = color.css_class"></li>
      </ul>
      <div class="result-box" :class="activeClass"></div>
    </div>
  </div>
</div>

<script src="https://unpkg.com/vue@next"></script>