Wrapping External Libraries with Vue JS Component
I will explain here my approach to wrap any external JS library with Vue components, so these can be used in any part of my Vue js application.
The goal is not ending up having part of my application written in vanilla JS and another part in Vue js.
I will use Pikaday as an example for this tutorial. It’s a popular date picker library that’s well tested.
The vanilla way:
The common way to set up external libraries in Vanilla Js is by manipulating the dom, here is an example:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Pikaday</title>
<link rel="stylesheet" href="css/pikaday.css">
</head>
<body>
<h1>Pikaday</h1>
<label for="datepicker">Date:</label>
<br>
<input type="text" id="datepicker">
<script src="pikaday.js"></script>
<script>
let picker = new Pikaday(
{
field: document.getElementById('datepicker'),
firstDay: 1,
minDate: new Date(),
maxDate: new Date(2020, 12, 31),
yearRange: [2000,2020]
});
</script>
</body>
</html>
We want to install our third-party library using our package manager, so our Vue js component takes care of that, instead of loading them in a vanilla way on the main web page. For Pikaday example that would be something like:
npm i pikaday
Now our job to adapt this working js vanilla code to work with Vue js. First of all, let’s move all the same markup to a new Vue Js component. We want to move the js code part to the mounted
Vuejs life cycle. This is important because we don’t want our js code to run before the dom is loaded. Also, you want to make sure to import your library JS and CSS to the Vue component.
<template>
<input type="text" id="datepicker">
</template>
<script>
import Pikaday from "pikaday"
import "pikaday/css/pikaday.css"
export default {
mounted() {
const picker = new Pikaday({
field: document.getElementById('datepicker'),
firstDay: 1,
minDate: new Date(),
maxDate: new Date(2020, 12, 31),
yearRange: [2000,2020]
})
}
}
</script>
So that should get the same results of vanilla approach. That’s easy, right? Now, we want to store the currently selected date in our Vue js component. We bind the value of date
in data in our component and let’s give it a default value
<template>
<input :value="date" type="text" id="datepicker">
</template>
<script>
import Pikaday from "pikaday"
import "pikaday/css/pikaday.css"
export default {
data() {
return {
date: "2018-04-12"
}
}
mounted() {
const picker = new Pikaday({
field: document.getElementById('datepicker'),
firstDay: 1,
minDate: new Date(),
maxDate: new Date(2020, 12, 31),
yearRange: [2000,2020]
})
}
}
</script>
Now when we change the date in the date picker, we notice that the state in the Vue component doesn’t change. Because the third party library doesn’t know about our frontend framework. Usually, these JS libraries provide events to help us notifying our framework when certain things happen.
So for this example, we will use onSelect
Pikaday event to change our Vue JS component.
mounted() {
const picker = new Pikaday({
field: document.getElementById('datepicker'),
.onSelect: () => {
this.date = picker.toString()
},
firstDay: 1,
minDate: new Date(),
maxDate: new Date(2020, 12, 31),
yearRange: [2000,2020]
})
}
Now, we can see that when we change the date in the date picker, our Vue component will keep track of its current date state.
I wrapped up this example in a reusable Vue Js component and published it on npm.