Back
Oct 3, 2016

How to include JQuery plugins in Angular 2 running via webpack

Hi everyone, today I’m gonna tell you how to use jquery in angular 2 running via webpack. This seemingly a quite trivial task, anyway, can put Angular 2 beginners on the spot when they try to do it. They may even put Angular 2 learning into a cold storage. Totally. Forever.

However, it’s not that difficult as Angular developers from Google and TypeScript guys from Microsoft might have wished.

How to use a jquery plugin? For this task we will need:

  1. angular2-webpack-starter
  2. jquery
  3. fullcalendar
  4. redactor (commercial editor, see details below)
  5. Types !?

Step 1. Just link the plugin

First of all let’s install angular2-webpack-starter. You'll make it, I’m sure. Next step is to install jquery and fullcalendar via npm. Now create an Angular 2 component or directive to store our jquery plugin. In this article I used fullcalendar example. To do that you have to create file calendar.components.ts in ...angular2-webpack-starter/src/app/home/ with this code inside:

import { Component, AfterViewInit, ElementRef } from '@angular/core';

import * as jQuery from 'jquery';
import "fullcalendar";

require('style!fullcalendar/dist/fullcalendar.css');

@Component({
  template: '',
  selector: 'calendar'
})
export class Calendar implements AfterViewInit {
  calendarElement: any;

  constructor(private elementRef: ElementRef) {}

  ngAfterViewInit() {
    this.calendarElement = jQuery(this.elementRef.nativeElement);
    this.calendarElement.fullCalendar({});
  }
}

Take a note of import lines, there we import the jquery first and the fullcalendar afterwards. Makes sense, isn’t it, Cap? We import in typescript jquery module into variable jQuery to use it later in the Angular 2 component, but we won’t call fullcalendar directly from the component as it is a plugin for jquery. Instead, we will use fullCalendar method which fullcalendar adds to jQuery objects while import. Also, you can use let jQuery = require("jquery") for import procedure, this matches ES5 notation standards, while import matches ES6.

The truth is that it is not even necessary to use import * as jQuery from 'jquery'; in each component at all, instead for angular2 import jquery we need to add next lines to WebPack configuration:

new webpack.ProvidePlugin({
  jQuery: "jquery"
})

This will allow using jquery with typescript from everywhere in the project. Read more.

The next step is to import native fullcalendar styles using require and webpack-style-loader. Note that we import styles apart from the component, as if we import them into Component decorator, they will be applied only to elements that have an attribute (with complex unreadable name) generated by Calendar component. But fullcalendar is generated by jquery, so there’re no attributes assigned by Calendar and no styles applied.

On AfterViewInit event we run jquery plugin on native HTML inside the component.

Don’t forget to add Calendar component to ngModules declarations. Now we are ready to ruthlessly replace content of ...angular2-webpack-starter/src/app/home/home.template.html with our component code:

<div class="card-container">
  <h4>Our FullCalendar example</h4>
  <calendar></calendar> <!--this is our fullcalendar-->
</div>

After WebPack dev server started, we can visit http://localhost:3000/to check our new linked fullcalendar example.

It would seem the end but attentive readers might notice that we used calendarElement with type “any” in the component. This is not so good because it disables static type safety check.

Step 2. Link @types

Did you remember how we linked header files in C++? So they are back! In the newest angular-webpack-starter version we are offered to use npm scope @types for this (https://www.npmjs.com/~types). We will use this way rather than any other one by following Microsoft recommendations for data type definitions. To install it we need to run:

npm install @types/jquery @types/fullcalendar --save-dev

So what’s the matter? The fact is that jquery types and protractor types try to export $. This is a known bug but still not fixed since 2014. I have found a way out by having made a fork for jquery types where $ export removed. To use this fork you should modify your package.json by changing this:

"@types/jquery": "^1.10.31",

to this:

"@types/jquery": "git://github.com/magnitronus/types-jquery.git",

Then remove node_modules/@types/jquery and run npm install.

What if the jquery plugin is totally new and there’re no any data type definitions for it in @types? You should create own ones, of course!

Step 3. Own data type definitions

There are two ways:

  1. Create the definitions and make a pull request to repository https://github.com/DefinitelyTyped/DefinitelyTyped, make sure you send it to types-2.0 branch because from this very branch the definitions get to npm scope @types.
  2. Create and save own definitions to file ...angular2-webpack-starter/src/custom-typings.d.ts.

I will use and describe the second way in this article just to show how to create own data types definitions for jquery plugins.

Let’s use commercial editor WYSIWYG for our example as there are no types for it (https://imperavi.com/redactor/). I’m not gonna stop on how to install WYSIWYG to node_modules, they say it’s not an issue for experienced developer.

The component code is similar to calendar’s code:

import { Component, AfterViewInit, ElementRef } from '@angular/core';
import "redactor";

require('style!redactor/redactor.css');

@Component({
  template: '',
  selector: 'redactor'
})
export class Redactor implements AfterViewInit {
  redactorElement: JQuery;

  constructor(private elementRef: ElementRef) {}

  ngAfterViewInit() {
    this.redactorElement = jQuery(this.elementRef.nativeElement);
    this.redactorElement.redactor();
  }
}

However, we don’t have types for this plugin and the simplest way is to add next code to custom-typings.d.ts:

interface JQuery {
  redactor(): JQuery;
}

With this we extend JQuery interface by telling typescript compiler that all Jquery objects (Jquery class instances) will have redactor() method. We can edit this definition later. F.e. if we want to use redactor() only with certain buttons like here https://imperavi.com/redactor/docs/toolbar/, we need to edit the definition this way:

interface RedactorOptions {
  buttons: string[];
}

interface JQuery {
  redactor(): JQuery;
  redactor(options: RedactorOptions): JQuery;
}

You can find one more type - jQueryStatic in jquery.d.ts. We may need to use it for static jQuery methods, i.e to define plugins with names like jQuery.something while plugins, described in this article, have names like jQuery.fn.something.

Conclusion

And this is the end. We had a look at how use jquery in angular 2 running via webpack. However, you better not to use jquery in your Angular 2 app because plenty of require-lines can make your code less readable and clear. And uncontrolled by Angular DOM elements bring a little disorder to a project’s structure.

In conclusion, I’d like to return to types one more time. TypeScript gives us a great opportunity to define types statically. Although it can be easily bypassed, it’s better not to do that as this is a quite powerful way to reduce a number of run errors, what is very important in fast-moving web app frontend development world.

Subscribe for the news and updates

More thoughts
Feb 3, 2025Technology
Figma for Developers: What Dev Mode Offers and How to Use It

This article explores Figma’s Dev Mode, a tool that streamlines design-to-code translation by enabling precise inspection, automated code generation, and seamless integration with design systems.

Dec 22, 2024Technology
Python and the Point Rush in DeFi

This article demonstrates how to use Python to automate yield calculations in decentralized finance (DeFi), focusing on the Renzo and Pendle platforms. It guides readers through estimating potential rewards based on factors like token prices, liquidity, and reward distribution rules, emphasizing the importance of regular data updates and informed decision-making in DeFi investments.

Dec 13, 2022Technology
How to create a timelapse video from frames

We’ll tell you how to create a video timelapse from a sequence of snapshots and provide customers with video playlists optimized for browser playback.

Apr 19, 2022Technology
Improve efficiency of your SELECT queries

SQL is a fairly complicated language with a steep learning curve. For a large number of people who make use of SQL, learning to apply it efficiently takes lots of trials and errors. Here are some tips on how you can make your SELECT queries better. The majority of tips should be applicable to any relational database management system, but the terminology and exact namings will be taken from PostgreSQL.

May 22, 2017Technology
Web Application Security: 10 Best Practices

Protection of WEB App is of paramount importance and it should be afforded the same level of security as the intellectual rights or private property. I'm going to cover how to protect your web app.

Feb 28, 2010Technology
Composing multiple views in Django

In UNIX way, each view should solve single task. This is good idea, but sometimes we need to mix logic of different views on same page. Filter, sort, paginate, or, for example, add comment on product page. In this article I'll show how we can mix such multiple views.