Build a Debug Directive

AngularJS Video Tutorial by

Enter Your Email Address to Watch This Lesson

Your link to unlock this lesson will be sent to this email address.

Unlock this lesson and all 184 of the free egghead.io lessons, plus get AngularJS content delivered directly to your inbox!



Existing egghead subscribers will not see this. Sign in.

Just one more step!

Check your inbox for an email from us and click link to unlock your lesson.




Edit

Build a Debug Directive

4:00 AngularJS lesson by

Explore some interesting techniques with AngularJS directives to create a debug directive using termination, priority, and the $compile service.

app.js

var egghead = angular.module("egghead", []);

egghead.controller("AppCtrl", function () {
    var app = this;

    app.people = [{"firstName":"Sonia","lastName":"Hodges"},{"firstName":"Benedict","lastName":"Morrow"},{"firstName":"Keegan","lastName":"Fields"},{"firstName":"Jade","lastName":"Martinez"},{"firstName":"Jaquelyn","lastName":"Suarez"},{"firstName":"Leo","lastName":"Hughes"},{"firstName":"Skyler","lastName":"Sharp"},{"firstName":"Genevieve","lastName":"Villarreal"},{"firstName":"Beau","lastName":"Hendrix"},{"firstName":"Lara","lastName":"Howard"},{"firstName":"Jonah","lastName":"Crawford"},{"firstName":"Kendall","lastName":"Lane"},{"firstName":"Kimberly","lastName":"Mcclain"},{"firstName":"Ingrid","lastName":"Salinas"},{"firstName":"Moses","lastName":"Mcpherson"},{"firstName":"Britanney","lastName":"Sweeney"},{"firstName":"Patricia","lastName":"Perez"},{"firstName":"Roth","lastName":"Heath"},{"firstName":"Nora","lastName":"Osborne"},{"firstName":"Giacomo","lastName":"Shepard"}]
});

egghead.directive("debug", function ($compile) {
    return {
        terminal: true,
        priority: 1000000,
        link: function (scope, element) {
            var clone = element.clone();
            element.attr("style", "color:red");
            clone.removeAttr("debug");
            var clonedElement = $compile(clone)(scope);
            element.after(clonedElement);
        }
    }
})

index.html

<!DOCTYPE html>
<html>
<head>
    <title>Egghead.io</title>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"/>
</head>
<body ng-app="egghead" ng-controller="AppCtrl as app">

<div class="well-large" debug>
    {{2 + 2}}
</div>


<ul class="well" debug>
    <li ng-repeat="person in app.people">
        {{person.lastName}}, {{person.firstName}}
    </li>
</ul>



<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.10/angular.min.js"></script>
<script src="app.js"></script>
</body>
</html>

egghead.io comment guidelines

egghead.io
Avatar

Explore some interesting techniques with AngularJS directives to create a debug directive using termination, priority, and the $compile service.

Marty
Avatar

This is a question that I derived from the video but it is off topic.

In the video scope and element had to be passed (injected) into the linking function so they could used. Then the $compile had to be passed (injected) into the directive so it could be used.

Sometimes functionality is injected directly into the link function and sometimes it's injected into the directive.

What is the difference between functionality passed into the linking function and functionality passed into the directive?

John
Avatar

The directive uses angular's injection (you can inject services, etc).

The link function only takes arguments (scope, element, attrs, ctrl, transclude) which can't be changed. You can't inject services, etc into the link function since angular always calls it with those arguments.

Marty
Avatar

John Lindquist: When you're writing your angular code all you get to see is the output in the browser you don't get to see the original expressions that were used to create that output.

If you want to see those you can use something call "ng-non-bindable" so that when I refresh here I can see the original expressions but now I don't get to see the final output. For debugging purposes maybe that would be a fun thing to see just to see what it originally was and then what the actual output is so you can compare and make sure everything's working just fine.

Let's set up a debug directive. I'm just going to create it there before I even start making it. So, egghead and directive, and we'll just say debug. From here we'll return our object. The first thing we'll do is say terminal, true. This basically means, "Don't run any other directives, stop here," and this will achieve that same result.

You can see that if I delete this and I refresh that it renders. But when I say terminal that means, "Don't do anything after this directive, just stop here." I'm also going to set a priority to something super high. This hasn't actually conflicted with anything I have seen but maybe it might for you. This just means, "Run this directive before any others run." We'll say, "Run it first, stop everything else."

What we can do now in our link function we can get our original scope, our original element and from there use those to compile it. We're going to clone the original element because we want to keep that original element there. We'll say "clone," we'll grab the clone. Then with the clone we'll need to remove the attribute of debug. This is super important or else you will crash your browser.

It crashes Chrome all the time if you do this because in the next step when you compile, which means we'll have inject the compiler. When we compile this, I'll compile our clone and I'll pass in the scope is the other thing you need for compiling. I get the cloned element and I just append it or add after the current element.

We'll say "clone to element." I hit refresh here you can see I get the original uncompiled element and then I get a compiled element, which is returned here and then added after the original element.

If you weren't to remove this attribute then this would crash the browser. You can try that on your own. I'm not going to do that right now.

One other thing I just want to do is just for debugging purposes I'll just say something like add an attribute of style, there's a million ways to do this, and we'll just say color red. I can see that this is obviously my debug stuff and then is not debug stuff.

I can just take this directive, I can add it anywhere I want. I want to debug this as well, two plus two is four and I can see that two plus two comes out to four.

This is a fun way of just building debugging tools to see what your element is before and what it is after it's compiled. Then once it's done you can actually just remove this directive all together or you could set up a service that would toggle true-false if you were in debug mode, however you want to achieve that.

But once you have that you can do whatever manipulation to this you'd want to see what's going on before and after the angular expressions have executed.