We are going to create a Toggle / Switch button component with Vue Js. Before starting, The basic thing to keep in mind that the Toggle / Switch button could have only one state i.e. On / Off or True / False. So all the implementation is based on this state.
You may like: Create Toggle / Switch Button in React
Similar Posts You May Like
We are using the Vue CLI to create our project. It’s very easy and saves a lot of time.
Create a ToggleButton.vue Component
The first step is to create the component. Go to the src/components directory and create ToggleButton.vue
file.
<template></template>
<script>
export default {
}
</script>
Next, add some HTML such as On / Off and a checkbox input field. Don’t confuse with the both On and Off text, we will handle it to the next section.
<template>
<label for="toggle_button">
<span>On</span>
<span>Off</span>
<input type="checkbox" id="toggle_button">
</label>
</template>
The next step is to add a default state that will handle the toggle button On / Off text.
<script>
export default {
data() {
return {
currentState: false
}
}
}
</script>
We have added a default state i.e. currentState
with the default false
value. It means the toggle button should display the Off text. We are going to use the v-if directive to handle the toggle state.
<template>
<label for="toggle_button">
<span v-if="currentState">On</span>
<span v-if="! currentState">Off</span>
<input type="checkbox" id="toggle_button">
</label>
</template>
<script>
export default {
data() {
return {
currentState: false
}
}
}
</script>
Or we can make it a bit better by using the computed property.
Computed properties are cached based on their reactive dependencies.
<template>
<label for="toggle_button">
<span v-if="isActive">On</span>
<span v-if="! isActive">Off</span>
<input type="checkbox" id="toggle_button">
</label>
</template>
<script>
export default {
data() {
return {
currentState: false
}
},
computed: {
isActive() {
return this.currentState;
}
}
}
The next step is to handle the checkbox field with the v-model directive. Let’s create another computed property with a getter and setter method and use it with v-model directive.
Computed properties are by default getter-only, but we can also provide a setter when we need it.
computed: {
isActive() {
return this.currentState;
},
checkedValue: {
get() {
return this.currentState
},
set(newValue) {
this.currentState = newValue;
}
}
}
<input type="checkbox" id="toggle_button" v-model="checkedValue">
Create Switch Button with CSS
The next step is to decorate our toggle button with the help of CSS. We are going to hide the checkbox field and add a switch button. Let’s add another span tag under the checkbox field to create a switch button.
<template>
<label for="toggle_button">
<span v-if="isActive" class="toggle__label">On</span>
<span v-if="! isActive" class="toggle__label">Off</span>
<input type="checkbox" id="toggle_button" v-model="checkedValue">
<span class="toggle__switch"></span>
</label>
</template>
<script>
export default {
data() {
return {
currentState: false
}
},
computed: {
isActive() {
return this.currentState;
},
checkedValue: {
get() {
return this.defaultState
},
set(newValue) {
this.currentState = newValue;
}
}
}
}
</script>
We have added the following classes i.e. toggle__button
to label, toggle__label
to span and toggle__switch
for the switch button. Let’s add some CSS to the applied classes.
<style scoped>
.toggle__button {
vertical-align: middle;
user-select: none;
cursor: pointer;
}
.toggle__button input[type="checkbox"] {
opacity: 0;
position: absolute;
width: 1px;
height: 1px;
}
.toggle__button .toggle__switch {
display:inline-block;
height:12px;
border-radius:6px;
width:40px;
background: #BFCBD9;
box-shadow: inset 0 0 1px #BFCBD9;
position:relative;
margin-left: 10px;
transition: all .25s;
}
.toggle__button .toggle__switch::after,
.toggle__button .toggle__switch::before {
content: "";
position: absolute;
display: block;
height: 18px;
width: 18px;
border-radius: 50%;
left: 0;
top: -3px;
transform: translateX(0);
transition: all .25s cubic-bezier(.5, -.6, .5, 1.6);
}
.toggle__button .toggle__switch::after {
background: #4D4D4D;
box-shadow: 0 0 1px #666;
}
.toggle__button .toggle__switch::before {
background: #4D4D4D;
box-shadow: 0 0 0 3px rgba(0,0,0,0.1);
opacity:0;
}
</style>
The next step is to check and see hows the toggle button looks like. Open the App.vue
file under the src directory and import our created ToggleButton component.
<script>
import ToggleButton from './components/ToggleButton.vue'
export default {
name: 'App',
components: {
ToggleButton
}
}
</script>
Now move to the template section to implement this component.
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<div class="box">
<p><strong>Basic Example</strong></p>
<ToggleButton />
</div>
</div>
</template>
The complete code for App.vue
should look like the below codes.
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<div class="box">
<p><strong>Basic Example</strong></p>
<ToggleButton />
</div>
</div>
</template>
<script>
import ToggleButton from './components/ToggleButton.vue'
export default {
name: 'App',
components: {
ToggleButton
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.box {
text-align:center;
margin-bottom: 30px;
}
</style>
This is not enough, we have to add more logics to our toggle component to make it more robust.
Dynamic Toggle State
As you already know that we have used the currentState
with the false
value to handle the toggle state. Nothing bad with this but we can’t make our component dynamic. Let’s take an example.
Let’s say we have a form with more than one toggle button. And what if we required a toggle button with the default true
value?
It is very easy to make the currentState
dynamic with the use of properties. Let’s define a property with the name defaultState
.
<script>
export default {
props: {
defaultState: {
type: Boolean,
default: false
}
},
data() {
return {
currentState: this.defaultState
}
},
computed: {
isActive() {
return this.currentState;
},
checkedValue: {
get() {
return this.defaultState
},
set(newValue) {
this.currentState = newValue;
}
}
}
}
</script>
And you can change the defaultState
property like the below codes. Notice the :
(column) before the defaultState
property, we used it because our defined property only accepts a boolean value.
<ToggleButton :defaultState="true" />
Attaching Event to Toggle Button
The most important part is to attach an event based on the toggle state. We need it to modify any state depends on the toggle button. For example, I want to highlight the area green when the toggle button state is true otherwise it should remain gray. And yes its depends on the returned value from the toggle button. Let’s attach an event that returns the state value.
computed: {
isActive() {
return this.currentState;
},
checkedValue: {
get() {
return this.defaultState
},
set(newValue) {
this.currentState = newValue;
this.$emit('change', newValue);
}
}
}
As you see, we have used the $emit
to create a custom event. Now go to the App.vue file and let’s use this change
event.
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<div class="box">
<p><strong>Event Handler</strong></p>
<div :class="{'active': toggleActive}" class="toggle_container">
<ToggleButton
v-on:change="triggerToggleEvent"
/>
</div>
</div>
</div>
</template>
<script>
import ToggleButton from './components/ToggleButton.vue'
export default {
name: 'App',
components: {
ToggleButton
},
data() {
return {
toggleActive: false
}
},
methods: {
triggerToggleEvent(value) {
this.toggleActive = value;
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.box {
text-align:center;
margin-bottom: 30px;
}
.toggle_container {
margin: 0px auto;
background: #efefef;
width: 120px;
padding: 10px 0;
border-radius: 30px;
transition: all .25s;
}
.toggle_container.active {
background: #e9ffef;
}
</style>
Disable Toggle Button
There are some cases when we only use the Toggle button only for display purposes. No click or event handler required for this kind of implementation. We can extend it by adding another property called disabled
with the default value false
.
<script>
export default {
props: {
defaultState: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
}
},
data() {
return {
currentState: this.defaultState
}
},
computed: {
....
....
....
}
}
</script>
<input type="checkbox" :disabled="disabled" id="toggle_button" v-model="checkedValue">
Now you can use this component with another property i.e. disabled
.
<ToggleButton :disabled="true" />