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 986 of the free egghead.io lessons, plus get Angular 1.x content delivered directly to your inbox!

Existing egghead members will not see this. Sign in.


8:40 Angular 1.x lesson by

A brief overview of using element in an AngularJS directive, and how to target one without jquery, and also how to use replace and compile function

Get the Code Now
click to level up

egghead.io comment guidelines


A brief overview of using element in an AngularJS directive, and how to target one without jquery, and also how to use replace and compile function

Nicholas Westby

How are you typing into a second window and having that markup be injected into a string into your first window in WebStorm? Looks really nifty.

Roman Ganchenko

Alt-tab >
Edit HTML fragment

In reply to Nicholas Westby

I don't get the 'this.link' 'return link' logic. Why do we assign link like this.link but then refer to it in compile section like just 'link'?


I updated the code to show the proper "var link" approach (I had this corrected with an overlay on YouTube, but missed it in migrating the videos).

This approach is simply a convenience, nothing more. You can leave the link function as an anonymous function "link: function(){...}" if you'd like. The only tricky part is that a compile function returns a link function, so using compile (which is an edge case) will look much different than the standard way of just using "link: function()" on a directive definition object".

In reply to Karen

You were probably just demoing features but this approach should not be used in actual app as directive function is not executed repeatedly. And having multiple instances of directive breaks this example. Am I correct?


angular 1.5.3 seems to provide more jquery support e.g. eq(1) and find('selector')

In reply to egghead.io

Another high standard tutorial from John. So easy to follow. I doth my cap.

Question: Why append the element in compile and not in the link function since they can both append to the directive element?

As far as I can see, the benefit of compile is when properties of the directive need manipulation. The element is available to compile in case it need manipulation as a result of changing directive properties.

Are there any other tutorials which unleash what compile can really do?

In reply to egghead.io

John Lindquist: I want to talk briefly about angular elements and how they are a bit different from J-Query elements. Also, a little bit about the compile function, but not too much technical detail, just enough to get your brain going.

Here, I have a dumb-password element with a template of, "Hello, world." Basically, this is just to check that it's working. What I want to do is make this a template that has two things listed inside of it, so the first thing we'll be an input with a type of text, ng-model of say, "Model input." Then, the next one can be a div that just has the model input showing.

If I refresh here, let's just type something. We're good to go. You can see that we have dumb-password, wrapping our div, and then, inputting div inside of that div. One thing I'm going to do here. I've talked about this before, but I want to say, "Replace," and just say, "True," here. Because what that's going to do is -- watch when I refresh. You'll see that the dumb-password is gone away, and now, it's simply replacing dumb-password with that div.

Whereas before, this was wrapped with dumb-password, now it's just the div. This is going to make it a little bit easier to go under the children of the div, in just a second here. Because what I want to do is when the password equals the word "password," we'll do a little alert thing there. Say our linking function, we're going to say, "Scope watch."

There's another thing I haven't talked about, but it's pretty easy to set up. This just means we're going to watch our model input. We want to change as we can check the value for whatever we want. So, we'll say, "If value equals the word 'password', then console log change it," or something. We'll type in here say, "Password and our console say, 'change it'." I'll do it again. That's working.

What we want to do is dive into our element and change a class on an element inside of our template. What we could do right now is say, "Element, and get," put, "children." Then, "Get the children," and that will be the first one, because we want to grab this guy. Then, say, "Toggle class and alert box and alert."

Now, this, I think, is a terrible way of doing this, actually. I believe I did that wrong. Where's password? There we go. I didn't have to dive into that first level. Sorry, I got confused with "replace" for just a second there.

We dove into it and grabbed the second element, so this was the first one and this one is the second one, then toggled the class of an alert box. We just added the class on to it.

Now, this is a nasty way of looking this element up, because typically like in J-Query you will use something like, "find." You will use a selector to find it, or find by ID and things like that. That's actually not supported in Angular-JS. That's more for reasons of testing and things like that.

What we can do is get a reference to the element before we even put it on the doms. What I'm going to do is create an element in here, so let's look into our template. I'm going to grab this guy, delete him, and then, I'm going to create an angular element from him. Let's call it, "valid hold enter," or something like that.

Use angular element to create an element from this string. Then, we're going to talk about -- I mentioned, I'm going to talk about the compile function and this is where I'm going to do it. The compile function takes your template stuff, so this will be our template element, say, "TL, LM," or whatever. From here, we can just append our -- what do we call it -- valid element on to it.

I'm going to delete our linking function, real quick. You'll say it make a come-back really soon, but for right you can see that this is still working. It's still bound. We have a reference to the valid element. We append it to our template, but we lost all the scope stuff. So we need to rewire up the scope stuff.

What I'm going to do here is return. You return a linking function from the compile function. We can't reference a linking function inside of our object here anymore. We have to actually return it from here. We can just do this, "return," and then, everything should be wired up. "Wired," or I guess, "Password," is what I want to type.

You can see that it's still looking up the element by element "children-1." Instead, what we can do now, instead of saying, "Element children-1," I can just say, "Valid element." Now, I can say, "Password." You can see that "valid element" is a reference to that actual element. We're not searching for it. We're not finding it. We're not using the select or anything.

We have an actual reference to the element itself. We can apply any sort of -- adding classes or manipulate it however we want to. We, actually, don't even need this reference to the element to do that sort of stuff, because we have a full reference to the element there.

Just one note here before I finish. Just to keep this a bit cleaner. I'd like to create here something like this, or I just say, "This link," is that. It is that? I guess I copied and let's paste from the history. It's this one.

Then, from there, I can just say, "Return link," instead of returning the functions out of there. This will still work. Now, we have, just to quickly review, there's nothing to show in here. It's just the component itself. We had a "restrict" which is the element. It's going to replace the entire thing.

That's not wrapped in, if we look at the elements. This isn't wrapped in the dummy, or the dumb-password, it's just the div with the two elements inside of it. During the compile phase, we are appending him onto our template. That's right here. This is our template and this is -- we're just appending the valid element in there. Then, from there on out, all we're doing is watching for the input to change.

When it does change, we have our reference to that element and we can talk with the class or whatever we want to on that element itself. Hopefully, that makes sense. I'll go into more detail on things like "scope watch" and angular element and the compile phase in future videos. But for right now, hopefully, that clears might clear some things up for you.

Joel's Head
Why are we asking?