Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at cf.Objective() 2011 (Minneapolis, MN) with:

Accessing $document Properties In AngularJS

By Ben Nadel on

This is just a quick little blog post about something silly that tripped me up in AngularJS for a few minutes the other day. I had injected the $document object in my Controller and was attempting to read the cookies; but, it kept showing up as "undefined". After a little head-scratching and a little console-logging, I realized - d'uh - $document is a jQuery collection, not a direct reference to the HTML document object.

When you inject $document into your AngularJS context, you get a jQuery collection (or jQLite collection) that contains the document object. This means that in order to access the properties of the document, you either have to use the .prop() method or unwrap the document reference:

  • <!doctype html>
  • <html ng-app="Demo" ng-controller="AppController">
  • <head>
  • <meta charset="utf-8" />
  •  
  • <title>
  • Accessing $document Properties In AngularJS
  • </title>
  • </head>
  • <body>
  •  
  • <h1>
  • Accessing $document Properties In AngularJS
  • </h1>
  •  
  • <!-- Load jQuery and AngularJS. -->
  • <script type="text/javascript" src="../jquery/jquery-2.1.0.min.js"></script>
  • <script type="text/javascript" src="../angular-1.2.16/angular.min.js"></script>
  • <script type="text/javascript">
  •  
  • // Create an application module for our demo.
  • var app = angular.module( "Demo", [] );
  •  
  • // I control the root of the application.
  • app.controller(
  • "AppController",
  • function( $scope, $document ) {
  •  
  • // Attempting to reference $document properties directly.
  • console.log( $document.title );
  • console.log( $document.cookie );
  • console.log( $document.body );
  •  
  • console.log( ". . . ." );
  •  
  • // Get the underlying properties using jQuery.
  • console.log( $document.prop( "title" ) );
  • console.log( $document.prop( "cookie" ) );
  • console.log( $document.prop( "body" ) );
  •  
  • console.log( ". . . ." );
  •  
  • // Get the underlying properties by unwrapping document object.
  • console.log( $document[ 0 ].title );
  • console.log( $document[ 0 ].cookie );
  • console.log( $document[ 0 ].body );
  •  
  • }
  • );
  •  
  • </script>
  •  
  • </body>
  • </html>

When we run the above code, we get the following output:

undefined
undefined
undefined
. . . .
Accessing $document Properties In AngularJS
_ga=GA1.2
<body>
. . . .
Accessing $document Properties In AngularJS
_ga=GA1.2
<body>

As you can see, the first three properties come back as "undefined" because we are trying to read them directly from the jQuery collection. Once we access the underlying DOM node (ie, document object), however, we can read the properties correctly.

This post is here primarily to drive the point into my mental RAM. But, maybe it will be helpful to others. And, as a side note, I should say that this is not true for $window - when AngularJS injects $window, it's nothing but a reference to the actual window object. AngularJS provides it as an injectable in order to create decoupling and to provide better testability.

Tweet This Groovy post by @BenNadel - Accessing $document Properties In AngularJS Thanks my man — you rock the party that rocks the body!



Reader Comments

I understand there are many other reasons why you would want access to $document, but is there a reason you wouldn't use the $cookies or $cookieStore module?

Reply to this Comment

@Derek,

Great question. I didn't really need full cookie functionality - I just need to check for the existence of a single cookie. And, I didn't happen to have the ngCookies module installed, so this just felt like the quick-and-dirty approach. That said, if I did have $cookies installed, I would have used it.

On a related note, though, I have heard mixed reviews about the $cookies implementation; but, I think that was maybe before it was broken out into its own module. All to say, I haven't really looked into the ngCookies module much yet. I should take a closer look.

Reply to this Comment

@Ben

After going through some of the change history on GitHub, it looks like there are some key features for the ngCookie module that aren't available until the more recent builds, and may be implemented at the 1.3.0 milestone. Here is a link to the change request that mentions it.

https://github.com/angular/angular.js/pull/2459

Reply to this Comment

@Derek,

Oh cool - that may explain some of the issues I was having way back when I first tried cookies. Looks like it's probably all up to snuff now. Thanks!

Reply to this Comment

I think this shows that accessing $document properties should always be used behind a service instead in a controller. I don't think controller code should directly reference jquery objects or a dom nodes.

Reply to this Comment

@Liviu,

Yeah, you're probably right. I don't think Service should really be accessing jQuery objects either... but, at least with a Service you only have one point of failure that can be injected into other components.

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.