Include External JavaScript Libraries In An Angular 2 TypeScript Project

I’ve been a JavaScript developer for a while now, but with the release of Angular 2, I’ve been inspired to pick up TypeScript.   However, what happens when I want to use one of my hundreds of available external JavaScript libraries in my project?

I’m going to share how to use your favorite JavaScript libraries in a TypeScript Angular 2 application.

UPDATE 03/06/2017: Want an updated, more thorough set of instructions for using JavaScript libraries in your TypeScript application?  Check out this revisited article I wrote on the subject.  The information below is still valuable and worth a read regardless.

As of right now Angular 2 is in its first beta stage, but breaking changes shouldn’t be introduced (per the Angular 2 developers) so any stable release should be fine.

Before we look at a very functional project, let’s discuss the few small things that makes this possible.

To include a JavaScript library in your TypeScript application you must first include it in your HTML file as a script tag.  To use the library you must add the following to one of your ts files:

Replace libraryVar with a variable, function, or class within your JavaScript library.  At this point it is ready for use.

Because it can be a little tricky to grasp, we’re going to make a full project to demonstrate this.

Create a new project directory somewhere on your computer and execute the following from your Terminal (Mac and Linux) or Command Prompt (Windows) after navigating into it:

Of course you need the Node Package Manager (NPM) already installed.

With the project directories and files in place, run the following to get all the Angular 2 dependencies:

Remember, I’m using the first beta of Angular 2, but you can play around with versions.

Open your project’s package.json file and add the following two scripts:

This allows us to watch for file changes and run a live server for our application.

Now open your project’s src/tsconfig.json file and include the following:

These are TypeScript settings for compiling.

This brings us to our first HTML file.  Open your project’s src/index.html and include the following code:

We’re including all the Angular 2 scripts and making use of the my-app custom selector.  However, pay close attention to the following line:

This is the external JavaScript library that we’re going to use.  It is jsSHA, a hashing library that I’ve used in many of my other projects.  Download the library from GitHub and drop it in your project’s src/js directory.

With our project foundation laid out, it is time to work with our final two files.

Starting with our project’s src/app/app.ts file, open it and include the following TypeScript code:

Notice the highlighted lines as everything else is fundamental to a typical Angular 2 application.  I’ve declared jsSHA since it is a class inside of the jsSHA library.  Then in the constructor method I use the library exactly as it is described in the official documentation.

The final file is our project’s src/app/app.html file.  Open it and add the following few lines of HTML:

The {{hash}} text is pulling data from our App class’s hash variable.  It is the SHA-512 HEX that jsSHA creates.

To test out our project, open two Terminal windows.  In the first window execute the following:

In the second Terminal, execute the following:

You should be able to access your project via http://127.0.0.1:8080/src/ in your web browser.

Conclusion

I typed out way more than I really needed to, but since it is a tricky subject to grasp I thought it would be necessary.  I didn’t understand it at first from the other documentation online.  You essentially need to declare some component of the external library before you can start using it.

If the library you plan to use includes a set of type definitions, you may want to read this followup article I wrote on the topic.

A video version of this article can be seen below.

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.

  • Brad Martin

    Nice man. I’ll make sure this stays bookmarked for future reference.

    • Yea it took me too long to figure out for how silly it is.

  • Great explanation. Bookmarked.

  • BrianDeSousa

    I’m in a similar situation as you though still trying to get acquainted with typescript and angular 2. In your example I assume the jsSHA library is pure Javascript and does not have matching .ts files. I’m wondering what happens when your typescript transpiles into normal Javascript.. What happens to the calls to the jsSHA script. Have you ever experienced a situation where the transpiled code is not compatible with the external script?

    • BrianDeSousa

      Great article by the way!

    • I can’t imagine it causing any issues. Do you have an example where this might be causing issues?

      • BrianDeSousa

        Nope no examples, was just curious if you’ve experienced something like that.

  • dreeco

    https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/jssha

    Do you know about DefinitelyTyped? It’s typings for library such as jssha (and many others) that you can include in your project. Reference your library and you will be able to compile your ts file while keeping benefits from typescrit (methods arguments types and return values, etc).
    Cheers

    • I didn’t know about that, but in all fairness, not all JavaScript libraries on the internet will exist in this project. My solution is great for that scenario.

      Thanks for sharing though 🙂

      • dreeco

        Yep of course 🙂 but you would be surprised about the quantity of libraries having typings 🙂

  • karthick kumararaja

    is it possible to include a phonegap based cordova plugin into ionic..?? thanks in advance

  • Zhenyang Hua

    I have found even without declaring the class/function in the library, I am still able to use the library methods after adding the script tag to the index.html. Could you explain how the declare method makes a difference here? btw, I do found the error for referencing the library goes away after declaring it, but without declaring, i can still use it.

    • Yes it should still compile even with the warnings and errors. JavaScript is a forgiving language and isn’t restricted to variable type definitions. As long as TypeScript builds the JS file, it will work.

      If you’re using TypeScript and ignoring the errors and warnings, you might as well stop using TypeScript and just use JavaScript.

      • Zhenyang Hua

        Thanks for the explanation! That way it is loaded as global script. I found using System.import(url) will also do the trick and the promise is resolved as a module which lives inside of the component scope if it is used in a component.

  • Cagatay Civici

    How do you load the js/sha.js dynamically without the script tag?

    • I don’t believe this is possible

    • Vahid N.

      It’s possible. Add ‘jssha’: ‘node_modules/jssha/src’ to map section of the systemjs.config.js file and then use
      var jsSHA = require(“jssha”);

  • Ryan Marchock

    I am new to Angular2 and i used your tutorial as a guide to import my own javascript library but it didn’t work. https://github.com/marchock/vertical-blocks .. Does the library file need to be reworked for it to work?

    • What doesn’t work about it? Are there errors? Does it take you to myspace.com when it shouldn’t? You see where I’m going with this? I need more information to be able to help effectively.

      Best,

      • Ryan Marchock

        Sorry about that. I have followed all the steps in your tutorial and everything works. Next i tired to add my own javascript library and i get an error displaying ‘VerticalBlocks is not defined’. I do not understand why this error occurs and how to fix it.

        • I’m pretty sure you want to do this in your constructor:

          You’re trying to print something that hasn’t yet been defined I think.

          Let me know if that makes a difference.

          Best,

          • Ryan Marchock

            I reworked my library to use a module pattern instead of a prototype pattern and now everything is working. Thanks for the help

  • Michal Marek

    The cleaner solution would be to download the typings file for jsSHA (DefinitelyTyped has it) using something like tsd or typings. Then you can simply import {jsSHA} from ‘jssha’ to get it working and your IDE will hint things for you.

    • Yes of course, but like I said in another comment, not all libraries will exist in DefinitelyTyped. jsSHA just happens to exist, but my angle was to assume it doesn’t exist.

      • John Warmann

        Hi Nic, Great video!! Had been trying to figure this out. This method works well. I’ve tried using the “preferred” way of using type definitions using typings. I probably missed something so couldn’t quite get that to work. Could you show a quick demo on the steps?

        • It’s on my agenda to show how to get the typings from DefinitelyTyped.

  • Arun

    Nic – How do I do the same with Ionic 2? I want to include an xml to json library https://www.npmjs.com/package/x2js and unfortunately its not available via tsd install x2js –save.

    • Not all NPM packages are going to be compatible with Ionic 2 as many were designed to be run with Node.js or via a desktop.

      That said, you should be able to utilize my tutorial as long as the library is compatible. What errors are you getting when you try to use it?

      • Arun

        I wanted to include https://github.com/johngeorgewright/angular-xml (to transform xml to json) and I just couldn’t get it to work and I ended up using https://www.npmjs.com/package/xml2js (using npm install xml2js) . Does Ionic 2 external libraries have to node libraries? Also, we don’t have index.html in Ionic 2 app folder – are you saying I should just edit the www/index.html file and include the external js file?

        • Yes you would include standard browser based JavaScript libraries in the www/index.html file.

          Not sure what your asking in the rest of your question.

          Best,

          • Arun

            As per Ionic 2 documentation (http://mhartington.io/post/ionic2-external-libraries/) to include any external libraries (e.g lodash) you have to npm install the library and include the typings definition (you can find typings files at this link http://definitelytyped.org/tsd/) to use it :

            npm install lodash –save
            typings install lodash –ambient –save

            If your external library doesn’t have a corresponding “typings” definition file you can’t use it in Ionic2/Angular2?

            I will try the steps you have suggested above to include another javascript library but is this the standard way of including external javascript libraries? Or is there a way to create typings definition file for external javascript libraries?

          • You would follow Mike’s tutorial if (a) typings exist for the library and (b) you wish to use those typings.

            There are probably (no proof on this) more JavaScript libraries than there are websites in the world. The odds that every library will contain a type definition file is unlikely.

            The tutorial I wrote will show you how to use ANY browser based JavaScript library in a TypeScript project.

  • Yaseen L Meridja

    Hey Nic, I was scratching my head over how to use all the good libraries that are already out there with Angular 2, it seems to me that Angular 2 operates almost like an island.
    My question is, can your approach be used to integrate JQuery libraries like morris.js charting or any number of other very interesting ones?
    It seems counterproductive to expect all the legacy libraries to be ported specifically to Angular 2. What are your views on that?

    • Remember these libraries have to work via a browser. If the library works in the browser you should be able to use them. Front end frameworks need front end libraries. You get a little more freedom if doing Node.js.

      That said, jQuery will probably work, but like you mentioned it would probably be counter productive. In my opinion at least. Go all in with Angular.

      • Yaseen L Meridja

        And I guess these browser libraries will have to export some named functions, lots of libraries use IIFE idiom to do their thing, will it be difficult in that case to integrate with Angular 2?

        • I think you’ll be fine

          • Yaseen L Meridja

            That’s not an answer!
            In any case the way forward is using Systemjs for proper module loading and even throwing in jspm for good measure.

  • Piccaza

    Hi Nic,
    I am trying to include pixijs library into ionic2 app, but getting following error.
    I am getting error in following line >> declare var PIXI: any;

    Unexpected token (3:8) while parsing file: /Users/Piccaza/Phaser/ionic/game/app/pages/home/home.js

    Do you have any different tutorial about doing this in ionic2 app?

    • Are you sure you are using TypeScript? I don’t see anything long with that line. Where have you placed it? Placement DOES matter.

      Best,

      • Piccaza

        Thanks, mine was not typescript project. Recreated the project with –ts, then resolved this issue.

  • Vasco Gaspar

    Hello Nic. Do you have any idea on how to integrate skrollr like this? I’m just not getting how to attach the data-attributes to skrollr events. Thank you!

    • I don’t know what Skrollr is. Want to start there?

  • Yassmeen Mahmoud

    Hi Nic I included the jquery.flot.js library in the index.html and then wanted to use it in a BarChartComponent like this

    import {Component,ElementRef} from ‘angular2/core’;

    declare var $:any;
    @Component({
    selector: ‘bar-chart’,
    templateUrl:’templates/barchart.component.html’
    })
    export class BarChartComponent{
    plotObj: any;
    constructor(private elRef: ElementRef) {}
    ngAfterViewInit(){
    var bar_data = {
    data: [[“January”, 150], [“February”, 8], [“March”, 4], [“April”, 13], [“May”, 17], [“June”, 9]],
    color: “#3c8dbc”
    };
    this.plotObj = $.plot($(this.elRef.nativeElement), [bar_data], {
    grid: {
    borderWidth: 1,
    borderColor: “#f3f3f3”,
    tickColor: “#f3f3f3”
    },
    series: {
    bars: {
    show: true,
    barWidth: 0.5,
    align: “center”
    }
    },
    xaxis: {
    mode: “categories”,
    tickLength: 0
    }
    });
    }

    }

    and then I get in the console that $.plot is not a function. What did I do wrong?

  • Yassmeen Mahmoud

    That helped alot . Thanks. Keep going 🙂

  • Mike Trieu

    Hey great article. Quick question ~ Is it possible to implement this as a service? I tried declaring a 3rd party object in a service.ts and imported it, but it didn’t seem to work. It works great in components and directives however. I want to build a service wrapper around the 3rd party library for easy reuse, but can’t seem to get the declaration to work in the service.

    • What have you tried?

      • Mike Trieu

        Here’s a plunkr to some of my code: https://plnkr.co/edit/VIZPKuQSf7Vv5E18r6QL?p=info

        Tried to load 3rd party upload service in filestack.service.ts, then imported it into fbwins.component.ts, but when the object gets returned by the service, its undefined. The script src is included in index.html.

        I feel like it would make sense to implement some 3rd party libraries as services, so that they could be easily imported and reused, I could be wrong though.

        • Based on what I saw, I think your problem is this:

          declare var filepicker: any; != private filepicker: any;

          You are trying to return this.filepicker which has never been defined. In the constructor maybe do something like this?:

          this.filepicker = filepicker;

          Make sense?

          Best,

          • Mike Trieu

            awesome, that worked!

            Previously, I had “this.filepicker = filerpicker” in the ngOnInit() function, but i guess those are only included components and directives.

          • Glad you got it working 🙂

  • Abubaker Shangab

    Splendid

  • Kevin Aud

    “As of right now Angular 2 is in its first beta stage, but breaking changes shouldn’t be introduced” lol remember the days when we believed this

    • Sad times….

      Every single beta and release candidate broke everything. Now that things are stable hopefully things no longer change.

      • I think we’re good now for a little while. The framework seems fairly complete.

  • Kevin Quiring

    Hello, I used this post to use external libraries and it worked great and you did a good job of explaining how to do it. However, I am running into a new problem with one specific external library and Angular AOT. I have multiple external javascript libraries that work with JIT and AOT. This one library however works with JIT, but not AOT. It is called “css-element-queries.” I try doing what you said and worked for the other libraries but I get the error

    EXCEPTION: Uncaught (in promise): TypeError: ResizeSensor is not a constructor
    TypeError: ResizeSensor is not a constructor

    This library consists of two different .js files. One js file is trying to make a call to the other and that is when this error happens. It’s weird because it works in JIT though. Any ideas to what may be happening?

    • Maybe some kind of race condition between the two files? Not sure the order in which the AoT compilers processes things.

      • Kevin Quiring

        If you’re interested I created a public repo with all the details you need to see the issue.

        https://github.com/quiringk/ConstructorError.git

        This repo consists of Angular Quickstart with angular AOT added. I
        removed the angular quickstart template and replaced it with the first
        example from “css-element-queries”. If you clone the repo, run
        “npm install”, and then “npm start”, and witness the example working
        perfectly (Adjust the screen size and see the header change color and
        sizes). If you run “npm run build:aot && npm run lite:aot” you
        will see the example does not work and you will see the errors I have
        been describing.

  • shikhar bansal

    Is there any way to include js files (which do not have any exported module) in Ionic 2 Project?

  • Sudhir Govekar

    i have libraries which are loaded in index file and i am using it in angular2 component
    example
    declare var libraryVar: any;

    what will be the libraryVar ..?

    • Whatever your JavaScript library is. You should probably read my whole article as this is explained.

      • Arpit Bhargava

        i run library from golden layout in index.html in angular2
        prj…
        I
        donot want this script in index.html, i just want a selector tag in
        golden layout component to instantiate the golden layout, i want script
        to be just in golden layout on init of component, below function did not
        help me to remove the golden layout script loading from index.html var
        js = document.createElement(“script”);

  • Ferandro

    Hi Nick, I have some problem as I shared this question in stackoverflow. (http://stackoverflow.com/questions/41696055/uncaught-typeerror-exists-is-not-a-function-when-attempting-to-use-serial-port) Please can you help me.

  • raghul

    how to get system mac address in angular2

    • Robert Kaucher

      You cannot. Browser-based JS is not going to have access to system information like that.

      • raghul

        thanks Robert, how to get unique client id ?

      • raghul

        thanks

  • PALANI KUMAR PARAMASIVAM

    Hi,
    I am new to angular. I am using morris. js file in angular 2 ts. In dev build it is working. But if i am using prod build, it is not working. It shows ‘Morris undefined’. Kindly do the needful.

  • Nisism Levy

    FGood article but you neglected to explain the mysterious code below:

  • Nisism Levy

    Good article but you neglected to explain the mysterious code below:

    System.config({
    packages: {‘app’: {defaultExtension: ‘js’}}
    });
    System.import(‘app/app’);