JavaScript
Article

How to Integrate jQuery Plugins into an Ember Application

By Lamin Sanneh

This article was peer reviewed by Craig Bilner. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

With its ubiquity, jQuery still plays a vital role in the web development world. Its regular employment shouldn’t be a surprise especially when using a framework like Ember. This framework has components that are similar to jQuery plugins in that they are both designed to have a single responsibility in your project.

In this article, we will develop a simple Ember component. This tutorial will showcase how to integrate a jQuery plugin into an Ember application. The component acts as a wrapper for the plugin, which shows a list of picture thumbnails. Whenever we click a thumbnail, a bigger version of it is displayed in the picture previewer. This works by extracting the src property of the clicked thumbnail. Then, we set the src property of the previewer to that of the thumbnail. The complete code of this article can be found on GitHub.

With this in mind, let’s start working on this project.

Setting up the Project

First of all, let’s create a new Ember project. To start, execute this command on the CLI:

npm install -g ember-cli

Once done, the project can be created by running:

ember new emberjquery

This will create a new project in a folder named emberjquery and install the required dependencies. Now, move into the directory by writing cd emberjquery.

The project contains different files that we’ll edit in this tutorial. The first file you have to edit is the bower.json file. Open it and change your current Ember version to 2.1.0. The jQuery plugin I have created for this project is available as a Bower package. You can include it in the project by adding this line to your bower.json file:

"jquerypic": "https://github.com/LaminSanneh/sitepoint-jquerypic.git#faulty"

Now, to install the plugin and the new version of Ember run the command:

bower install

Since this plugin is not an Ember component, we need to manually include the required files. In the ember-cli-build.js file, add the following two lines right before the return statement:

// Lines to add
  app.import("bower_components/jquerypic/js/jquerypic.js");
  app.import("bower_components/jquerypic/styles/app.css");

  return app.toTree();
};

These lines import two files and include them in the build. One is the plugin file itself and the other is the CSS file for the plugin. The stylesheet is optional and you are free to exclude it if you intend to style the plugin by yourself.

Creating a New Plugin Component

Once you have included the plugin in the application, let’s start creating a new component by executing the command:

ember generate component jquery-pic

This command creates a class file and a template file. In the template file, paste the contents from the bower_components/jquerypic/index.html file. Place the content in the body tag, excluding the scripts.

At this point, the template file should look like this:

{{yield}}
<div class="jquerypic" >
  <div class="fullversion-container">
    <img src="http://lorempixel.com/640/480/nature/1" alt="" class="full-version" >
  </div>
  <div class="thumbnails">
    <img src="http://lorempixel.com/640/480/nature/1" alt="" class="thumbnail">
    <img src="http://lorempixel.com/640/480/nature/2" alt="" class="thumbnail">
    <img src="http://lorempixel.com/640/480/nature/3" alt="" class="thumbnail">
    <img src="http://lorempixel.com/640/480/nature/4" alt="" class="thumbnail">
    <img src="http://lorempixel.com/640/480/nature/5" alt="" class="thumbnail">
  </div>
</div>

In the class file, add a function called didInsertElement:

import Ember from 'ember';

export default Ember.Component.extend({
  didInsertElement: function () {

  }
});

We are now at a crucial point. With jQuery, plugin initialization usually happens within a document.ready function as shown below:

$(document).ready(function(){
  //Initialize plugin here
});

With Ember components, instead, this initialization happens within a special function named didInsertElement. This function is called when a component is ready and has been successfully inserted into the DOM. By wrapping our code inside this function, we can guarantee two things:

  • The plugin is initialized only for that component
  • The plugin will not interfere with other components

Before initializing our plugin, let’s use the component in its current state. To do that, create an index template using the command:

ember generate template index

Then add the following code to the template to use the component:

{{jquery-pic}}

Once done, load the Ember server with

ember serve

With this command the server is started. Open your browser of choice and access the URL specified by the command-line interface. You should see a list of thumbnails below a picture previewer. Please note that when you click on a thumbnail, nothing happens. This happens because we haven’t hooked up the plugin event handlers. Let’s do it!

But before describing how to perform a correct initialization, I will show you a mistake that many developers make. This solution might seem to work at first but I will prove you that it isn’t the best by showing a bug it introduces.

Ember Component Initialization

To show the problem, let’s start by adding the following code to the didInsertElement function:

$(".jquerypic").jquerypic();

When not using Ember, this is how you would normally initialize the plugin. Now, check your browser window and click on the thumbnails. You should see that they are loaded in the big picture previewer as intended. All may seem to work fine, right? Well, check what happens when we add a second instance of the component. Do this by adding another line to the index template containing the same code I showed before. So, your template should now look like this:

{{jquery-pic}}
{{jquery-pic}}

If you switch to the browser window, you should see two instances of the component showing up. You can notice the bug when clicking on the thumbnail for one of the instances. The previewer change for both instances and not just for the clicked one.

To fix this issue, we need to change our initializer a bit. The correct statement to use is reported below:

this.$(".jquerypic").jquerypic();

The difference is that we are now using this.$ instead of just $. The two component instances should now behave properly. Clicking on the thumbnails for one instance should have no effect on the other component.

When we use this.$ in a component we refer to the jQuery handler specific for that component only. So, any DOM manipulation we do on it will only affect that component instance. Moreover, any event handler will be set just on that component. When we use the global jQuery property $, we are referring to the whole document. That is why our initial initialization affected the other component.

I had to modify my plugin to demonstrate this bug and this might be the topic of a future article. Nevertheless, the best practice when manipulating a component’s DOM is the use of this.$.

Destroying the Plugin

Well, so far we’ve seen how to set up event handlers. Now it’s time to show the way to remove any event we have set up with our plugin. This should be done when our component is going to be removed from the DOM. We should do this because we don’t want any redundant event handler hanging around. Luckily, Ember components provide another hook called willDestroyElement. This hook gets called every time Ember is about to destroy and remove a component instance from the DOM. My plugin has a stopEvents method which is callable on the plugin instance. This method should be called in the special hook Ember provides for us. So, add in the following function to the component:

willDestroyElement: function () {
  this.get('jquerypic').stop();
}

Modify the didInsertElement function so that it look like this:

didInsertElement: function () {
  var jquerypic = this.$(".jquerypic").jquerypic();
  this.set('jquerypic', jquerypic);
},

In the didInsertElement function, we just stored the plugin instance in a property of the component. We perform this operation so that we can have access to it in other functions. In the willDestroyElement function, we are calling the stopEvents method on the plugin instance. Although this is good practice, our application has no way to trigger this hook. So we will set up a demonstration click handler. In this handler, we will call the stopEvents method on the plugin instance. This allows me to show that all the events handlers have been removed like we intended to.

Now, let’s add a click function handler to the component:

actions: {
  stopEvents: function () {
    this.get('jquerypic').stop();
  }
}

Then add a paragraph tag to the component template as shown below:

<p {{action "stopEvents"}} >
  Stop Events
</p>

When this tag is clicked, it calls the stopEvents action that destroy the plugin. After clicking the paragraph, the plugin should no longer respond to click events. To enable again the events, you have to initialize the plugin as we did in the didInsert hook.

With this last section, we have completed our simple Ember component. Congratulations!

Conclusions

In this tutorial you’ve seen that jQuery plugins still play a vital role in our careers. With its powerful APIs and the JavaScript frameworks available, it’s very useful to know how to combine the two worlds together and make them work in harmony.

In our example the component acts as a wrapper for the plugin, which shows a list of picture thumbnails. Whenever we click a thumbnail, a bigger version of it is displayed in the picture previewer. This was just an example but you can integrate any jQuery plugin you want.

Once again, I want to remind you that the code is available on GitHub.

Do you use jQuery plugins in your Ember apps? if you want to discuss about them, feel free to comment in the section below.

  • http://thejsguy.com/ David Tang

    Great post! If this.$() finds elements within the component, what would you use to get a reference to the component element itself?

    • http://lswebapps.com/ Lamin Sanneh

      I assume ‘this’ would do just fine to get the class instance of the component. Or do you mean the root element of the component?

      • Loretta Daly

        Chief Executive of Yahoo! – Marissa Meyer , is recommending people to start freelancing from home… Something that I have been doing for over 2 years now. My profit, for this year alone is $53k so far and all I needed was nothing more than my laptop and several hrs of free time each week at home working online job over internet company, despite that i have a full-time employment beside it. Great thing is that even newbies, can get $50/hr with no trouble and the earnings can go even higher over time… This is where i started. df….

        http://www.Insureon.DA.CX

      • http://thejsguy.com/ David Tang

        ya, the root element since ‘this’ would refer to the component and this.$() scopes to anything inside the root element.

        • Gabor Babicz

          Just call `this.$()` with no arguments, it’ll return the root element as a jQuery object. You can also use `this.get(‘element’)` to get the raw DOM element.

          • http://thejsguy.com/ David Tang

            thanks!

        • http://lswebapps.com/ Lamin Sanneh

          Yes Gabors answer resolves that. Thanks Gabor for sorting that one out.

Recommended

Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in JavaScript, once a week, for free.