Skip to content

Instantly share code, notes, and snippets.

@idanb11
Forked from esfand/angular-jqlite.adoc
Last active August 29, 2015 14:07
Show Gist options
  • Save idanb11/c5d36f4fbb97cd3f4aab to your computer and use it in GitHub Desktop.
Save idanb11/c5d36f4fbb97cd3f4aab to your computer and use it in GitHub Desktop.

Angular jqLite

jQuery and Angular

Angular doesn’t depend on jQuery. In fact, the Angular source contains an embedded lightweight alternative: jqLite. Still, when Angular detects the presence of a jQuery version in your page, it uses that full jQuery implementation in lieu of jqLite. One direct way in which this manifests itself is with Angular’s element abstraction. For example, in a directive you get access to the element that the directive applies to:

angular.module('jqdependency', [])
  .directive('failswithoutjquery', function() {
    return {
      restrict : 'A',
      link : function(scope, element, attrs) {
               element.hide(4000)
             }
    }
});

(see this example in action in this plunkr)

but is this element a jqLite or jQuery element? It depends. The manual states:

All element references in Angular are always wrapped with jQuery or jqLite; they are never raw DOM references. So it will be a jqLite element only if jQuery was not detected by Angular. The hide() method only exists for jQuery elements, meaning this example only works when Angular uses jQuery. If you (accidentally) switch the order of AngularJS and jQuery script tags in your page, this code breaks! Shuffling script tags around may not happen very often, but it bit me when I started modularizing our codebase. Especially when you start using a module loader (like RequireJS), this can rear it’s ugly head. For RequireJS, I solved it by explicitly declaring that Angular does in fact depend on JQuery in the shim config.

Another takeaway might be that you shouldn’t call jQuery specific methods through Angular’s element wrapper. Instead you can use $(element).hide(4000) to make it abundantly clear that you do, in fact, depend on jQuery. In that case, changing the script tag order won’t break the directive.

Angular jqLite

jqLite is a tiny, API-compatible subset of jQuery that allows Angular to manipulate the DOM in a cross-browser compatible way. jqLite implements only the most commonly needed functionality with the goal of having a very small footprint.

angular.element is a function in module ng which wraps a raw DOM element or HTML string as a jQuery element.

To use jQuery, simply load it before DOMContentLoaded event fired.

If jQuery is available, angular.element is an alias for the jQuery function. If jQuery is not available, angular.element delegates to Angular’s built-in subset of jQuery, called "jQuery lite" or "jqLite."

Note: all element references in Angular are always wrapped with jQuery or jqLite; they are never raw DOM references.

Angular’s jqLite

jqLite provides only the following jQuery methods:

Adds the specified class(es) to each of the set of matched elements
function jqLiteAddClass(element, cssClasses) {
  if (cssClasses && element.setAttribute) {
    var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
                            .replace(/[\n\t]/g, " ");

    forEach(cssClasses.split(' '), function(cssClass) {
      cssClass = trim(cssClass);
      if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
        existingClasses += cssClass + ' ';
      }
    });

    element.setAttribute('class', trim(existingClasses));
  }
}

jQuery/jqLite Extras

Angular also provides the following additional methods and events to both jQuery and jqLite:

Events

$destroy - AngularJS intercepts all jqLite/jQuery’s DOM destruction apis and fires this event on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM element before it is removed.

Methods

  • controller(name) - retrieves the controller of the current element or its parent. By default retrieves controller associated with the ngController directive. If name is provided as camelCase directive name, then the controller for this directive will be retrieved (e.g. 'ngModel').

  • injector() - retrieves the injector of the current element or its parent.

  • scope() - retrieves the scope of the current element or its parent.

  • isolateScope() - retrieves an isolate scope if one is attached directly to the current element. This getter should be used only on elements that contain a directive which starts a new isolate scope. Calling scope() on this element always returns the original non-isolate scope.

  • inheritedData() - same as data(), but walks up the DOM until a value is found or the top parent element is reached.

Usage

angular.element(element);

Argument: element - HTML string or DOMElement to be wrapped into jQuery. Its type is stringDOMElement.
Returns: Object - jQuery object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment