Create Toggle / Switch Button with Vue Js

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>
Vue Toggle Button Example

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" />