Skip to main content
Ben Nadel at InVision In Real Life (IRL) 2019 (Phoenix, AZ) with: David Epler
Ben Nadel at InVision In Real Life (IRL) 2019 (Phoenix, AZ) with: David Epler ( @dcepler )

Accessing $document Properties In AngularJS

By 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.

Want to use code from this post? Check out the license.

Reader Comments

2 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?

15,688 Comments

@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.

15,688 Comments

@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!

2 Comments

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.

15,688 Comments

@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.

1 Comments

I am working on Angular Project which is an single Page Application site. I have only single home page and <head> in index.html but I want to access unique meta attributes information for each page. Can you please help me how can I make this happen?
This is the information I need to access for meta for all pages saparately.
I have a service which is accessing meta but not its attributes that are keywords and its content.
<meta name="keywords" content="cheap international flights"/>

Please help

1 Comments

HI , first i would like to thank for your tutorial, i am beginner of angularjs following your way is this possible to access html tags ? i tried but nothing is displayed.

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel