Create a custom toggle component in Vue.js. 🎛
Vaibhav Khulbe
Posted on September 11, 2020
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!
What are we making❓
This:
Kickstart the custom toggle 🦵
Step 1️⃣: The setup
Fire open your terminal to create a new Vue project:
vue create custom-toggle
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
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>
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;
}
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>
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>
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:
- Components Basics — Vue.js
- Creating Custom Inputs With Vue.js by Joseph Zimmerman
- Adding v-model Support to Custom Vue.js Components by Joshua Bemenderfer
- Learn Vue 2: Part 25 - Custom Input Components by Laracasts
Thanks for reading, I appreciate it! Have a good day. (✿◕‿◕✿)
Can you spot the difference? 😝
— Microsoft Developer UK (@msdevUK) September 10, 2020
Image source: https://t.co/rhSnxZLNJa#DevHumour #WFH #RemoteWorking pic.twitter.com/MRmH1aKB9u
📫 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.
Posted on September 11, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.