Angular 2 and Ionic 2 are very new developer frameworks. Although not as new, the TypeScript language has been getting much attention as the recommended way to develop with Angular 2 and Ionic 2. TypeScript is a superset of JavaScript that turns it into a typed language. The code is written as TypeScript and then compiled into JavaScript.
This is where things get weird. What happens when you want to use a JavaScript library in your TypeScript project? Although similar, JavaScript is obviously not TypeScript and can cause some issues at compile time.
There are a few ways to do this, but we’re going to take a look at how to include your favorite vanilla JavaScript libraries in an Ionic 2 TypeScript project.
There are a few requirements to make what comes next possible:
We need Node.js because the Node Package Manager (NPM) ships with it. This is how we can install the Ionic 2 CLI as well as another package that we’ll see later in the tutorial. The Android SDK will let us build Android applications and Xcode will let us build iOS applications. It is a good idea to have at least one of those.
To get the most out of this tutorial, we’re going to start with a fresh Ionic 2 project. Using the Terminal (Linux and Mac) or Command Prompt (Windows), execute the following:
ionic start ExampleProject blank --v2 --typescript
The --v2
tag indicates that we want to create an Ionic 2 project rather than the default Ionic Framework 1 project. The --typescript
tag indicates that we want our project to be developed in TypeScript rather than vanilla JavaScript. The appropriate CLI must be installed to make use of these tags.
From here on out, all Terminal or Command Prompt activity will happen from within our ExampleProject directory.
With the project created, let’s add our build platforms. Using the Command Prompt or Terminal, execute the following:
ionic platform add ios
ionic platform add android
It is important to note that if you’re not using a Mac, you cannot build for the iOS platform.
For this example we’re going to look at using a common JavaScript bcrypt library called bcryptjs, useful for hashing passwords. Maybe you decide you want to require pin code authentication in your application. You’re going to want to hash the pin so people cannot decipher it.
To include the JavaScript library, enter the following from your Terminal or Command Prompt:
npm install bcryptjs --save
Technically we could start using this library, but it will feel a bit dirty since we’re using TypeScript, not JavaScript. We’ll revisit using a vanilla JavaScript library towards the later end of this tutorial.
To make JavaScript libraries more TypeScript friendly we need to download the type definitions for the libraries we wish to use. There is a Node package called Typings that will allow us to install these definitions.
To install Typings, execute the following from the Command Prompt or Terminal:
npm install -g typings
If you’re using a Mac or Linux machine, you may need to use sudo
to install this package with administrator permissions.
Before we can install the proper type definitions we may need to make an adjustment. As of May 2016, Ionic 2 defaults to an older version of the Typings package. If this is the case, we need to wipe it out. At the root of the project, remove the typings directory. Before we reinstall the core dependencies we need to update the typings.json file. Open it and replace everything with the following:
{
"dependencies": {},
"devDependencies": {},
"globalDevDependencies": {
"es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654"
}
}
To reinstall the dependencies execute the following:
typings install
With the configuration updated we can install the bcryptjs type definitions. From the Command Prompt or Terminal, execute the following:
typings install dt~bcryptjs --save --global
We’re not in the clear yet. If at the time of reading this, Ionic is still using the older Typings package, we need to rename a particular file. Rename typings/index.d.ts to typings/main.d.ts.
We can now start to use bcryptjs in our project.
To be more specific in what we’re going to accomplish, we’re going to hash a string, and compare a matching and different string against the hash. This will demonstrate bcrypt comparisons.
Open the project’s app/pages/home/home.ts file and include the following code:
import {Page} from 'ionic-angular';
import * as bcryptjs from "bcryptjs";
@Page({
templateUrl: 'build/pages/home/home.html'
})
export class HomePage {
public hash: string;
public assertTrue: boolean;
public assertFalse: boolean;
constructor() {
this.hash = bcryptjs.hashSync("nraboy", 8);
this.assertTrue = bcryptjs.compareSync("nraboy", this.hash);
this.assertFalse = bcryptjs.compareSync("yobarn", this.hash);
}
}
Notice that we are importing bcryptjs
which matches the type definition. In our HomePage
class we have three public variables which will be bound to our HTML UI for rendering.
Finally, in the constructor
method we hash a new string and compare two different strings against the hash.
The UI is going to be very simple. For this particular example we only want to display the three public variables from our TypeScript file.
Open the project’s app/pages/home/home.html file and include the following markup:
<ion-navbar *navbar>
<ion-title>
Ionic 2
</ion-title>
</ion-navbar>
<ion-content class="home">
<ion-card>
<ion-card-header>
Bcrypt Example
</ion-card-header>
<ion-card-content>
HASH: <br />
Compare "nraboy": <br />
Compare "yobarn":
</ion-card-content>
</ion-card>
</ion-content>
The first comparison should return true and the second should return false since it doesn’t match what we hashed.
There will often be scenarios when type definitions don’t exist. I mentioned earlier that without type definitions, the usage of vanilla JavaScript could feel dirty. We’re going to take a look at this scenario now. Let’s take it a step further and say that the JavaScript library isn’t registered on NPM either.
Head over to GitHub and download the latest bcryptjs file. You should be able to download it here.
Place this file in the project’s www directory and then open the project’s www/index.html file to include the following markup:
<html lang="en" dir="ltr">
<title>Ionic</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<link ios-href="build/css/app.ios.css" rel="stylesheet">
<link md-href="build/css/app.md.css" rel="stylesheet">
<link wp-href="build/css/app.wp.css" rel="stylesheet">
<ion-app></ion-app>
<script src="cordova.js"></script>
<script src="build/js/es6-shim.min.js"></script>
<script src="build/js/Reflect.js"></script>
<script src="build/js/zone.js"></script>
<script src="build/js/app.bundle.js"></script>
<script src="bcrypt.min.js"></script>
Notice in particular the line towards the bottom where we include the JavaScript library. Head back into the project’s app/pages/home/home.ts file because it will look slightly different when we try to work with vanilla JavaScript files. Include the following code:
import {Page} from 'ionic-angular';
declare var dcodeIO: any;
@Page({ templateUrl: 'build/pages/home/home.html' })
export class HomePage {
public bcryptjs: any;
public hash: string;
public assertTrue: boolean;
public assertFalse: boolean;
constructor() {
this.bcryptjs = dcodeIO.bcrypt;
this.hash = this.bcryptjs.hashSync("nraboy", 8);
this.assertTrue = this.bcryptjs.compareSync("nraboy", this.hash);
this.assertFalse = this.bcryptjs.compareSync("yobarn", this.hash);
}
}
What is truly important here is the following line:
declare var dcodeIO: any;
We are declaring dcodeIO
as any
to prevent compiler errors. We won’t receive any IDE autocomplete, but at least we’ll be able to compile. We can further prepare the library for use in the constructor
method with the following line:
this.bcryptjs = dcodeIO.bcrypt;
The official bcryptjs documentation says that browser based usage must use the library like above.
We saw two different scenarios for including JavaScript libraries in an Ionic 2 TypeScript project. The preferred approach is to use NPM to download the JavaScript library and download the type definitions with Typings, but should those options not be available, you can manually include the JavaScript library and declare it as any
in the TypeScript file.
For more examples on using JavaScript libraries in Angular 2 and including type definitions, check out some of my previous posts on the topic.