Category Archives: VueJS

vue-pin-code-input-component

Vue PIN code input component

At the end of this post you’ll learn how to implement a basic vue pin code input component.

One of my projects required an authorization layer for protecting some resources.

I ended up building a quite simple Vue Component that can be integrated in any app and that can be easily extended for any needs.

The template of the Vue Pin Code Component looks like this:

<template>
    <div>
        <div class="input-group">
            <input v-model.number="pin_0"
                   v-on:keyup.right="pin_focus('pin_1')"
                   v-on:keypress="is_valid_pin_value($event, 'pin_0')"
                   ref="pin_0" type="text" placeholder="0">
            <input v-model.number="pin_1"
                   v-on:keyup.left="pin_focus('pin_0')"
                   v-on:keyup.right="pin_focus('pin_2')"
                   v-on:keypress="is_valid_pin_value($event, 'pin_1')"
                   ref="pin_1" type="text" placeholder="0"">
            <input v-model.number="pin_2"
                   v-on:keyup.left="pin_focus('pin_1')"
                   v-on:keyup.right="pin_focus('pin_3')"
                   v-on:keypress="is_valid_pin_value($event, 'pin_2')"
                   ref="pin_2" type="text" placeholder="0">
            <input v-model.number="pin_3"
                   v-on:keyup.left="pin_focus('pin_2')"
                   v-on:keypress="is_valid_pin_value($event, 'pin_3')"
                   ref="pin_3" type="text" placeholder="0">
        </div>
    </div>
</template>

The controller of the component:

export default {
     data: function () {
         return {
             pin_0: null,
             pin_1: null,
             pin_2: null,
             pin_3: null
         }
     },
     computed: {
         pin: function () {
             return ${this.pin_0}${this.pin_1}${this.pin_2}${this.pin_3}
         }
     },
     watch: {
         pin: function () {
             this.$bus.$emit('PIN/change', this.pin)
         },
         pin_0: function (nv) {
             if (nv.toString().length !== 0) {
                 this.$refs.pin_1.focus()
                 this.$refs.pin_1.select()
             }
         },
         pin_1: function (nv) {
             if (nv.toString().length !== 0) {
                 this.$refs.pin_2.focus()
                 this.$refs.pin_2.select()
             }
         },
         pin_2: function (nv) {
             if (nv.toString().length !== 0) {
                 this.$refs.pin_3.focus()
                 this.$refs.pin_3.select()
             }
         }
     },
     methods: {
         pin_focus: function (ref) {
             this.$refs[ref].focus()
             this.$refs[ref].select()
         },
         is_valid_pin_value: function (e, pin_N) {
             const char = String.fromCharCode(e.keyCode)
             const is_value_selected = this[pin_N] !== null && this.$refs[pin_N].selectionStart === 0 && this.$refs[pin_N].selectionEnd === this[pin_N].toString().length
             if ((this[pin_N] === null || this[pin_N].toString().length === 0 || is_value_selected) && parseInt(char, 10) >= 0 && parseInt(char, 10) <= 9) {
                 return true
             }
         e.preventDefault()     } }
 }

What it does:

The data contains properties required for binding the current values of the pin between the template and the controller.

A computed property pin is kept up2date using changes done to any data variable.

We’re using keyup.left, keyup.right and keypress events to switch between each input of the PIN.

Each time the pin computed variable is changed, we $emit an event. See my previous post for learning how to implement Observer Pattern in Vue.

Integrating the PIN Component in our app is as easy as:

<InputPIN />

this.$bus.$on('PIN/change', function (value) {
    console.log('the pin:', value)
})

That’s all. Our Vue PIN Input component is ready.

Convert seconds to Days, Hours, Minutes, Seconds

Learn how to convert number of seconds into days, minutes, hours and seconds.


That’s it. You can now create a countdown timer, display the difference between two dates or just print  the time until something great happens.

var seconds = 1001110 // 11 days 14:05:10

// compute the number of days
var days = Math.floor(seconds / (3600*24))
seconds -= days*3600*24

// compute the number of hours
var hours = Math.floor(seconds / 3600)
seconds -= hours*3600

// compute the number of minutes
var minutes = Math.floor(seconds / 60)
seconds -= minutes*60

You now have 4 variables with values as follows:

days === 11
hours === 14
minutes === 5
seconds === 10

Bonus! Learn how to pad the values with 0 so that they look pretty 😀

function str_pad_left (string, pad, length) {
     return (new Array(length+1).join(pad)+string).slice(-length)
}

console.log(str_pad_left(minutes, '0', 2)) // "05"

Check this article to learn how to create a countdown timer.

Vue Countdown Timer Component

At the end of this post you’ll learn how to implement a basic vue countdown timer component.

In a web project I built I needed to show the user a countdown timer until the UI/options will expire.

So I ended up building a quite simple Vue Component that can be integrated in any app and that can be easily extended for any needs.

The template of the Vue Countdown Timer Component looks like this.

I’ve also used Bootstrap class to make the timer red when there’s no more time left.

<template>
    <div>
        <p :class="{'text-danger': total<=0}">
            <strong>{{minutes}}</strong>
            <strong>:</strong>
            <strong>{{seconds}}</strong>
        </p>
    </div>
</template>

The controller of the component:

export default {
    props: {
        time: {
            type: Number,
            default: 0
        }
    },
    data: function () {
        return {
            total: '',
            minutes: '--',
            seconds: '--',
            interval: 0
        }
    },
    mounted: function () {
        this.total = parseInt(this.time, 10)
        this.interval = setInterval(() => {
            this.tick()
        }, 1000)
    },
    methods: {
        str_pad_left: function (string, pad, length) {
            return (new Array(length+1).join(pad)+string).slice(-length)
        },
        tick: function () {
            var minutes = Math.floor(this.total / 60)
            var seconds = this.total - minutes * 60
            this.minutes = this.str_pad_left(minutes, '0', 2)
            this.seconds = this.str_pad_left(seconds, '0', 2)

            if (this.total <= 0) {
                clearInterval(this.interval)
                this.$bus.$emit('Timer/stop')
            }

            this.total -= 1
        }
    }
}

What it does:
The props defines which parameter to receive from the parent component. In our case it represents the number of seconds that the timer will start from.

The data contains properties required for showing the current state of the timer and for allowing us to control the interval handler.

When mounted, the component reads the time parameter and initializes the interval at which it will update the progress.

Tick method is executed as defined in the mounted interval. It will generate pretty minutes and seconds padded with ‘0’.

When the total seconds get to 0 we’ll also $emit an event. See my previous post for learning how to implement Observer Pattern in Vue.

 

Integrating the timer in our app is as easy as:

<Timer :time="300" />

That’s all. Our Vue countdown timer components is ready.

Vue Observer Pattern Implementation

Learn how to implement Vue Observer Pattern in your web app.

Probably one of my favorite design patterns is the Observer Pattern.
This design pattern allows you to subscribe and emit events from components of your app.

 

Different web frameworks offer different implementation of the Observer app.

Lucky me, implementing Observer in VueJS is piece of cake.

Actually the Observer in VueJS could be another Vue instance that we pass or make accessible by all our components.

import Vue from 'vue'
// create a new Bus which will handle all our events
const EventBus = new Vue()
// We need to assign the bus to the root component
Vue.prototype.$bus = EventBus

That’s all needed for the setup part.

You can now use this.$bus in all your Vue Components to subscribe and emit and dispatch events.

...
// some random component emits events
methods: {
    logout: function() {
        this.$bus.$emit('Some_Event/name', user)
    }
}
...
// some random component subscribes to the event
created: function() {
    this.$bus.$on('Some_Event/name', (data) => {
       this.logout_user(data)
    })
}

There are two possible ways of generating the events and it mostly depends on who we want to receive that event.

$emit – targeting whole app

The $emit method will trigger an event in the current instance.
This means that all subscribers will be notified of this event.

$dispatch – targeting parent components

The $dispatch method propagates the event up in the parent chain.
The first parent subscriber will stop the event from propagating further unless it returns true.

In my next post I’ll describe how to create a Countdown Timer Component in VueJS.
Adios!