Create a custom toggle component in Vue.js. 🎛

vaibhavkhulbe

Vaibhav Khulbe

Posted on September 11, 2020

Create a custom toggle component in Vue.js. 🎛

Making a custom component shouldn't be a mess. And what's better than using Vue's native features to create one! So let's do it. Let's make a custom or manual or whatever-you-want-to-call-it component from scratch!

Switch GIF

We have some switches to manufacture now...

What are we making❓

This:

Vue Custom Toggle Demo

I know, I know, it looks terrible, but let's just focus on the implementation :)

Kickstart the custom toggle 🦵

Step 1️⃣: The setup

Fire open your terminal to create a new Vue project:



vue create custom-toggle


Enter fullscreen mode Exit fullscreen mode

If you don't have the Vue CLI installed in your machine, you can find the installation steps on their official website.

Remove all other files and create the new ones just like what you see in the following project structure:



custom-toggle
│
└───public
│   │   index.html
└───src
│   │
│   └───components
│       │   Toggle.vue
│   │   App.vue
│   │   main.js
└───package.json


Enter fullscreen mode Exit fullscreen mode

As you see, our custom component will live in ./components/Toggle.vue file.

Step 2️⃣: Code App.vue

This is our entry point component. As you see, we have two things to display. First, is the toggle component itself and the text below that tells us the state of the toggle, whether it's turned on or off.

Under the <script>, use the data() method to return the default state of the component. Make it a boolean, so it can either be true or false. As I want to display the toggle to be "ON", hence I made it true by default.

Next, register the component which we'll make in the next step using the components option. Here's it's named appToggle. Make sure you import it correctly. Then register it on to the template making sure to use Vue's v-model directive to make two-way data-binding possible. Pass in the dataToggle property so that it can check the state dynamically.

As for the text below, we simply have a <p> tag which uses template syntax's string interpolation.

App.vue:



<template>
  <div>
    <app-toggle v-model="dataToggle"></app-toggle>
    <p style="text-align: center">Toggle: {{ dataToggle }}</p>
  </div>
</template>

<script>
import Toggle from "./components/Toggle";

export default {
  data() {
    return {
      dataToggle: true
    };
  },
  components: {
    appToggle: Toggle
  }
};
</script>


Enter fullscreen mode Exit fullscreen mode

Step 3️⃣: Code the toggle

Open up Toggle.vue file. Here we just need the two div elements (as we're making a custom element) for the "ON" and "OFF" states. These will be wrapped in a parent toggleContainer div.

In order to style them as we want, just give each an id of on and off respectively. The entire CSS styles applied are basic, so here's the styling you need:



.toggleContainer {
  margin-top: 40%;
  display: flex;
  justify-content: center;
  align-items: center;
}

#on,
#off {
  width: 40px;
  height: 20px;
  border-radius: 20px;
  background-color: lightgray;
  padding: 2px;
  text-align: center;
  margin: 10px -5px;
  cursor: pointer;
}

#on:hover,
#on.active {
  background-color: lightgreen;
}

#off:hover,
#off.active {
  background-color: lightcoral;
}


Enter fullscreen mode Exit fullscreen mode

Now comes the best part. In the script we first need to define the props object in order to pass data from App.vue to Toggle.vue. We only need the value of the parent component. This is because the prop we pass will determine which toggle is clicked, the "ON" or the "OFF". It's also useful to add dynamic CSS property changes.

As you can see from the above CSS code we have different background-color and active/hover pseudo-classes for both #on and #off. These are activated from the value prop. But for this thing to work, we need to use Vue's class/style binding feature with v-bind.

To implement this, we can either use v-bind:class or the shorthand syntax i.e. just :class. Here, just make the active object to be value (similar to dataToggle: true) in case of "ON" and the opposite active: !value (similar to dataToggle: false) in "OFF".

But we didn't implement what to do when we actually click on each of these toggle options! Ready for the last step? Here we go!

Add the @click click listener to the two children of the container. Pass on a new method switched() to it as shown:



<template>
  <div class="toggleContainer">
    <div id="on" @click="switched(true)" 
    :class="{active: value}">ON</div>
    <div id="off" @click="switched(false)" 
    :class="{active: !value}">OFF</div>
  </div>
</template>


Enter fullscreen mode Exit fullscreen mode

For the body of this method, we need to emit the new custom event on mouse click. Vue provides us with the $emit syntax for this functionality. The first parameter is the type of custom event, in our case, it's an input and the second parameter is isOn.

Toggle.vue:



<template>
  <div class="toggleContainer">
    <div id="on" @click="switched(true)" 
    :class="{active: value}">ON</div>
    <div id="off" @click="switched(false)" 
    :class="{active: !value}">OFF</div>
  </div>
</template>

<script>
export default {
  props: ["value"],
  methods: {
    switched(isOn) {
      this.$emit("input", isOn);
    }
  }
};
</script>

<style scoped>
.toggleContainer {
  margin-top: 40%;
  display: flex;
  justify-content: center;
  align-items: center;
}

#on,
#off {
  width: 40px;
  height: 20px;
  border-radius: 20px;
  background-color: lightgray;
  padding: 2px;
  text-align: center;
  margin: 10px -5px;
  cursor: pointer;
}

#on:hover,
#on.active {
  background-color: lightgreen;
}

#off:hover,
#off.active {
  background-color: lightcoral;
}
</style>


Enter fullscreen mode Exit fullscreen mode

And you've done it! 🥳 See how the text below the toggle changes from "true" to "false" and back!

You just made a custom toggle with Vue.js in a matter of minutes, that's what I like about this framework. It's really quick to make such components.

If you're stuck somewhere in the code or just want to interact with the output, I've embedded the CodeSandbox project below:


Where to next? 🤔

Brush up your custom component making skills with the following resources:


Thanks for reading, I appreciate it! Have a good day. (✿◕‿◕✿)


Can you spot the difference? 😝

Image source: https://t.co/rhSnxZLNJa#DevHumour #WFH #RemoteWorking pic.twitter.com/MRmH1aKB9u

— Microsoft Developer UK (@msdevUK) September 10, 2020

📫 Subscribe to my weekly developer newsletter 📫

PS: From this year, I've decided to write here on DEV Community. Previously, I wrote on Medium. If anyone wants to take a look at my articles, here's my Medium profile.
💖 💪 🙅 🚩
vaibhavkhulbe
Vaibhav Khulbe

Posted on September 11, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related