Show Notes

The crew talks about directives in AngularJS.

Transcript

 

LUKAS:

[Sings] Hey, Joe.

JOE:

Hey. [Sings] Na na, na na na na.

[Do you wanna have conversations with the Adventures in Angular crew and their guests? Do you wanna support the show? Now you can. Go to adventuresinangular.com/forum and sign up today!]

CHUCK:

Hey everybody, and welcome to Episode 12 of the Adventures in Angular podcast. This week on our crew, we have Joe Eames.

JOE:

Hey, everybody.

CHUCK:

Lukas Reubbelke.

LUKAS:

Hello.

CHUCK:

I'm Charles Max Wood from devchat.tv. And this week, we have a special guest, Federico Iachetti.

FEDERICO:

Hello from Argentina.

CHUCK:

Do you wanna introduce yourself really quickly, Federico?

FEDERICO:

I'm Federico Iachetti. I'm from Argentina. I work with Chuck on the devchat.tv page. I'm a Ruby developer, but I have some work done in Angular. I'm a pretty newbie in Angular, so I'm here mostly to listen.

JOE:

Federico, your accent is fantastic.

CHUCK:

[Chuckles]

FEDERICO:

[Chuckles] Thank you.

LUKAS:

I was just thinking, “Am I allowed to say something along those lines?” So thank you, Joe, for saying what I was thinking. So, I would like to say I'm actually here to listen to your accent. [Laughter]

FEDERICO:

Thank you. And I really don’t like my voice on recording, but thank you.

LUKAS:

You are probably going to get like 24 marriage proposals by the time this episode is released.

JOE:

Yes.

CHUCK:

Yeah, but Joe was the first. He's a home wrecker.

JOE:

[Laughs]

FEDERICO:

Yeah, Joe send me an email and we can talk.

[Laughter]

FEDERICO:

I mean, I'm a married man, so. [Laughter]

CHUCK:

All right, so let’s talk about Directives. Do you guys have a good definition for what directives are or how people should think about them?

JOE:

They are the most complex part of Angular. They are the hardest to define part of Angular – how about that?

LUKAS:

So a few things; directives are the first to essentially encapsulate custom functionality into a new HTML tag or property or attribute. I mean the entire premise of Angular is that you can extend HTML to do new things. So Angular itself is built on top of directives. It's directives all the way down. But it allows you to either decorate an existing element or create kind of these portable components, but I think really the best definition for me and what I'm most excited about, is directives are essentially DSL for your HTML, is that there's a bit movement towards semantic markup. Well, I think that ultimately directives allow you to really accomplish that by writing markup that really truly, if it's done properly, in a good eye towards architecture, to really convey the intent and the purpose of what that behavior for that HTML tag or attribute accomplishes.

JOE:

Yeah, it's interesting for everybody who’s listened to the first episode when Miško invented the first versions of Angular. His whole idea was a way for designers to go into HTML and specify things just in the HTML and basically build a working demo just by [unintelligible] with the HTML. So directives are really what Angular started out with is directives were the core idea behind it all. And like what Lukas said that’s making your HTML customizable with your own pieces, new pieces that you’ve built on your own.

CHUCK:

So I've seen directives kind of work in two ways. I've seen the one where you do like ng-if on an element, and then it shows up if it's true, and it doesn’t show up if it is false. And I've also seen directives that look more like text, so you may have like maybe ng-video tag for example. And then you build out the functionality around that so that it gets rendered to a regular HTML tag of some kind. Maybe a video tag with some controls stuff in it. Do you have to think about those differently?

LUKAS:

So like I said, you can use directives to either decorate an existing element. So that's for instance ng-if. What those commonly [unintelligible] is attributes is that you are actually decorating whatever element, so let’s say you a div with ng-if, is you're saying, “When this is true, this hide this or show this.” So you are kind of augmenting functionality of that div to be… it will just itself on or off. So you would specify that in your directive as “this is an attribute.” And by default, that's kind of what they default to. But with that said, it will often times something that's kind of a self-contained component, those generally will be like to find this element text. So if I wanted to write a uniform tag, I certainly could and that would be kind of a self-contained unicorn component, if you will.

JOE:

Yeah, so there are total of four ways to write directives, but two of them are not quite deprecated, but definitely recommend, and really only exist for support and compatibility with older browsers, bad problems with custom tags, and custom properties. You can write your directives using comments, you can write your directives using classes. And then you can write your directives using attributes and elements. And so the comments and the classes are really just to support older browsers. There are probably other reasons that people could come up with to use them that way, but elements and properties are really the ways that we write directives today.

Now as Lukas mentioned, attributes is the default way. In Angular 1.3, that’s changing the default elements and attributes. If you write a directive and don’t specify a default format, it won’t work in either. So that’s something interesting coming down the line. But I think that leads to another discussion on the purposes of Lukas. And Lukas talked about two purposes, right? The first one is you're building some kind of a custom component, like unicorn, I think the canonical one is like a tile for that represents a user, right? I've got a tile that has the information about a user, so I can just put on a user-tile tag somewhere on my page and then the information about the user now shows up.

And the other one that Lukas mentioned was decorators. If you wanna decorate up something existing HTML with ng-if, with ng-hide or ng-show to display or hide the element, you can also decorate them with things like ng controller. That's a way to decorate a tag and say, “Hey, I want a controller that controls this tag and all of its children and a scope that binds to it.” There's a third purpose for directives that is way less thought about, and that are structural directives. For example, the ng repeat, ng switch to actually less extent ngIf, is this way too, but these tags structurally modify your HTML, your DOM and set up something. And ng repeat is really just a

really good example to think about. You throw an ng repeat down, then all of a sudden, it explodes out into a whole bunch of repeating divs or whatever it is that you are going to be putting down and styling up your inner content with.

So there's really kind of three purposes to directives. And we think about them when we build custom directives mostly for the first two components, and secondly for decorating something and giving an existing tags some new functionality with a decorator. And what's interesting is in Angular 2.0, supposedly, this was actually represented in the language or in the framework. So when you build a directive, you will actually be building either decorator directive or a structural directive, or you will be building what they call component directive, the sort of widget, user tile type thing. But supposedly somehow, and I don’t know why I haven’t seen this and how this will work, but you'll actually be building three different things. And maybe there won’t be a directive anymore. It will be a component decorator and a structural or templaters. I've heard that term thrown around as well by the Angular team.

CHUCK:

Yeah, it seems like there are varied types and stages, or levels of complicatedness I guess. So I'm wondering what type of directive is easiest to get started with, and then how do you kind of grow from there to get to the more complicated types.

JOE:

Oh by far, it's just the component, right?

LUKAS:

Say when you are approaching directives is admittedly with like isolated scope and transclusion and different kind of the depths that you can take it, is if you really kind of step back. There is kind of a simplified world view that I like to use when thinking about directives, and that is there’s really kind of three main components that you'll build everything else off of, and that is your directive definition object, which I refer to as the DDO, the lib function and the controller function.

And a lot of times, you can actually build a directive that’s entirely capable, appropriate, just using your DDO saying, “When I have this attribute for this element. I just want to drop in these templates and I want it to maybe behave this way, like replace the HTML etcetera.” And so from the DDO, and once you understand that that’s just the configuration object for your directive, then you can dig into the link function, which allows you to actually do DOM manipulation on the element that you declared your directive on.

And then the controller is actually pretty easy because it works just like the controller in Angular an application. So kind of in a way, the directives is kind of the microcosm of an AngularJS application onto itself. But that is really I think when you understand like, “Hey, there's these complex things, but once you understand the DDO and the length function, and that a controller is just a controller.” I think people kind of take a deep breath realizing, “Oh, this is really just a composition of ideas and techniques that I'm already familiar with, and it's not that bad.”

CHUCK:

Let me see if I can restate some of these. So what you're saying that if you think about it in these three parts, your DDO is kind of the setup for your directive, and it tells it what it is and what to look for. And then your link function, I asked you this before the show, is essentially your jQuery object or whatever reference you have to the DOM, that allows you to manipulate it, and then the controller is what gives it the behavior that you want it to have, once you have everything else set up. Am I misstating anything there?

LUKAS:

I think that was a pretty reasonable explanation. Obviously, we could elaborate on that further, but I mean that’s what it is. The link function is one of the parameters is element, and the element is a jQuery object that you can perform DOM manipulation on. And then the controller is where you would obviously would wanna put kind of like your logic for that directive.

JOE:

Event handlers and things like that.

LUKAS:

Exactly. And then your DDO is just to set it up. It's just essentially a JavaScript object.

CHUCK:

One other thing that I'm wondering about, you’ve mentioned templates a few times, the templates, when would you use a directive, and when would you use a template with a controller that just gives it behavior?

JOE:

Are we talking about like ng include, right?

CHUCK:

Yeah.

JOE:

It's actually a good point. A lot of people, when they come into Angular will either start embracing directives, and use that entirely, or they will start embracing ng controller and ng include. And then use that entirely to break down their page into smaller pieces. And of course, some people will just… and then of course this is really sad, but you'll end up with a 500-line controller. You got a single controller for everything, and you don’t break down your page into smaller pieces at all. So once you do start bringing it down, you do have these options; you can either break it down using directives, you can break it down using ng include, pair it up with ng controller.

LUKAS:

I think it comes down to portability. I think with ng include, if I was doing just the header and the footer and the page and it wasn’t going to change, I might just take the path of least resistance, and use ng include. But the minute that I need to use it, that functionality in more than one place, then using ng include, you really lose that portability. So pulling that and extracting that out into a directive, allows you to use it over and over, and over, Which is a huge advantage in my opinion.

JOE:

There's also what you mentioned before which is the declarative nature of what Angular is and describing HTML. Sure, you could put your footer in an include, but if you have an element called Footer on your page, now of course that’s actually an HTML five element. [Chuckles] But maybe a slightly more business specific name to what you would have for your footer. And you have this element down there, now it's self-describing.

So it can be a little bit more complex to put it in a directive, because now you have a few more moving pieces than if you just do with an ng include and an ng controller. You also have to decide with ng controller and ng include, do you put the controller on the outside and the include on the inside, or you just put the include and then inside the template, you specify what the controller is, and therefore when you look at it, you see include, but you don’t know what controller that it uses until you dig in to the template, what that include is including.

So there's small moving pieces with using directive method, but using the include method, also kind of hides some intent, where directives might actually expose that intent by naming something really appropriately. And also then putting on really appropriate properties that indicate what's going on. Like you get properties that kind of describe the state of the object, at least how it is initially. And so when a developer comes through and sees this directive, you also see a set of property that kind of describe how that directive is set up initially and what's going on and what's it's purposes are and sort of customization for others.

CHUCK:

One other thing that occurs to me as well is that if you have a set of functionality that all kind of go together, for example, you have the controller that controls a certain part of the page, and you have enough of that, stuff that pulls it together in your link function, then putting it into a directive kind of communicates not only the intent like Joe said, but it also communicates this is sort of one thing. This is one collection of behavior from sort of front to back, within Angular. And so you get this nice encapsulation of a set of functionality.

JOE:

Right. And I wanna go back to something that Lukas said about the self-describing HTML. I had a conversation by John Lindquist at one point and he said, when he goes in to do any consulting with people one Angular, he says, “One of the things I can use to tell whether or not they know what they are doing in Angular, it's just by looking at the HTML. I never have to look at the code. I can just simply look at their HTML. And by looking at that and seeing their use of directives, that tells me how well they understand Angular and how well they are using it.” And I thought it was really interesting statement.

CHUCK:

That is really interesting.

JOE:

This is a little topic switching, but another pretty interesting thing about directives is I think when you first start out with Angular, and I remember this for me; I assume most people maybe hook on to this stage, when you start working with Angular, and all you know is you are throwing these little attributes into your page to make Angular work, and you're not thinking about the fact that those are directives, then you learn how to do directives and what you're doing is you're building these element-based directives with these widgets and components. And then at some point, it finally clicks like, “Oh my gosh, all these things that are on the page that makes Angular work, these are actually just directives. They are no different than a directive that I create.”

LUKAS:

and That’s when the lights come on I think for me, is anytime I talk about directives, is you start to build on these concepts. And then you can really tell when they get it, because it’s like, “Oh, that's what Angular is doing in the first place, is they are using Angular to build Angular.” So they kind of make that connection, that full loop. And it's really, really cool because I think then it's like I could do anything with Angular. And really kind of opens, broadened the horizons that really your HTML is if it can be done with JavaScript, and given browser limitations, you can really push the envelope really, really far using directives -- which is just amazing.

JOE:

Yeah, one of the things you start realizing you could do is if I'm creating some kind of component, a user tile component, a directive, that I realize pretty quickly that that doesn't have to be this big, huge monolithic piece. I can just start using attribute based directives with decorators to break down the full functionality outside of that. And some of that might be reusable, and some of those sub directives might not be reusable because they are very business specific to the user, but it's the way to componentize a bigger directive into smaller pieces, that can be dealt with on their own, and thought about on their own. And you start to see the ability to take pieces of Angular and put them into directives.

But I think that's the flow of how people learn to use directives. They start learning to use directives by building a big component, some kind of a widget. And then at a certain point, they start thinking, “I wanna break this down into a smaller pieces, and maybe they do smaller component directives within the bigger one, so if I've got my user tile, then maybe I'll have an address component to it. And maybe I've got permissions, sub directive to that.” But then pretty soon, they start seeing opportunities to put in decorators. So on the user, I can put in just an attribute, then that gives the user new capabilities, like the ability to switch states from being an enabled user to a disabled user just by adding on a directive that’s an attribute of the user element, rather than actually hard coding that right into the user. It's a very interesting process.

CHUCK:

I have to wonder if you’ve read refactoring books, they talk a bit about code smells. So are there code smells that tend to indicate to you that you need to take a certain set of functionality and then turn it into a directive?

LUKAS:

“Are you repeating yourself?” I think a really good one is, “Are you doing something in more than one place?” It's probably a good candidate for turning it into a directive. And then also the big Angular thing is do not do DOM manipulation in your controller. So anytime that I'm tempted to do that, it's just like, “Oh, I need to turn this into a directive.” So that’s another big one because that is ultimately where DOM manipulation happens is in the directive. Those are kind of my two big ones, but Joe, I’d love to hear your ideas.

JOE:

I'm sure you’ve done this as well, Lukas, you go through your Angular application and all of a sudden, you're seeing a piece and your are thinking, “I wish that piece is a smaller piece.” And you wouldn't necessarily, I think it goes back to that declarative intent, you are not necessarily going to reuse that piece somewhere else, but you think, “Oh, if I just collapsed all of these into one widget, then all of a sudden, I've got an easy declarative piece of my application that’s telling me what's going on.” In one of my PluralSight courses, I talked about these concept of breaking out a page into smaller pieces, and I show taking a big chunk of HTML that’s 120 lines long, and pulling out pieces and replacing them with a directive to just describe…

So one of them was like the menu system. I pull out all the HTML for the menu, just put in the menu directive. And then in the body, I pull out a bunch of pieces, some ng repeats and put in a user list directive. And then within that, there's a user directive and so and so forth. So that declarative idea of taking… and I think this comes potentially from just looking at your HTML and studying it and saying, “Where are the pieces that should be broken out into their own encapsulated box?” So I think that’s a third way to indicate when it’s time to build a directive. And obviously, there's a point where you're building something like, “Oh, I should be doing a directive here.” Just right from the beginning, you think, “This should be a directive.”

LUKAS:

Well said.

FEDERICO:

We are talking about when to create directives. I wanna ask a question about tricks or tips to create directives that you can use all over the place. Is there a good way to create a small directive that you can use all over the place, you can nest it… I don’t know if I'm clear on that.

JOE:

No, I got it. Makes sense. What do you think, Lukas?

LUKAS:

I'm going to say, if you are trying to promote reusability, especially within a company, really take the time to understand isolated scope. And in that sense, isolated scope, what it does is it kind of puts a fence around your directive. It allows you to define how the outside world can interact with your directive. And when you do that, essentially, your creating an API for that directive. So you might say, “I'm going to isolate the scope, so that only this property on the scope can communicate with the outside world.”

And so using binding isolated scope, you might have say, for instance, let’s say you have a user directive and you say, “I'm going to pass in this user object, and that’s what I'm going to bind on,” that prevents the outside world from creating unintended side effects into your directive and vice versa. And so my number one tip, is if you are building something that’s going to be passed around, and you are not sure of how people are going to be using it, there's kind of like, “Use this however you want,” [unintelligible] permutations is really take the time to lock that down with isolated scope. And the side effect is that it does provide a clear API of what your directive does and what it does not, and how to communicate with it.

JOE:

Awesome. I'll chime in with my own advice, and that would be to think about separation concerns. So even within a directive, even though directives are kind of the, you think of that as, “Oh, I need to manipulate the DOM. I need to build a directive.” But even within directives, you can have certain pieces where, “Here, I'm doing some manipulations to the display. And over here, I'm doing some business logic manipulation.” “I'm thinking about the fact that… these are actually two different concerns and I'm putting them within the same directive. So if I pull out the piece that manipulates the display into its own sub directive, then I might be able to reuse that in multiple places.

And of course if you also consider, “Oh, there's some business logic tied into something that maybe switches highlight level and goes from like a blank to a yellow, to a red, and back and forth.” But there's business logic. You can probably work and pull the business logic out, and now be able to reuse that component in multiple places. So that’s another place to get more reusable components. But really, it's just a matter of the smaller the directive is, the more likely it is to be reusable. Or to kind of go to the opposite direction, if you are doing something very business specific, the more comprehensive it is, that also makes it reusable, right? Because the user widget that works in one place might not work in another, unless you add more capabilities to kind of change its representation, but then be able to reuse it in multiple places.

CHUCK:

I have one final question before we get to the picks and that is in Joe’s example with the user list, would that be a directive that just warps around an ng include directive?

JOE:

I would say that one is probably not wrapping around an ng include. It's probably producing HTML inside of it that just says, “All right, now here's a user directive.” And I'll feed that user directive its particular user, so it takes in a list of users and it creates a repeating list of user directives, each one having its own user information. And this is a pretty simplistic case. It's hard to talk about by voice, but in that case, really you could just place with an ng repeat, but there are certainly more opportunities to a have business specific repeating lists, where ng-repeat doesn’t quite cut it. But for me, that would be structurally creating a whole bunch of user objects or user directives rather than a bunch of ng includes.

CHUCK:

Okay, that makes sense. All right, well lets go ahead and do the picks. Joe, do you wanna start us off?

JOE:

You bet. I only got one pick, and since we’ve been talking about this today. It's pretty early. It will be quite a bit of time, but I'm right in the middle of offering a course on directives for PluralSight.com and it's a pretty deep dive…

LUKAS:

Yay!

JOE:

It's a pretty deep dive. First few modules kind of start from ground zero, where you may have not have ever built directive, but then I do get really deep into like how to recreate ng repeat and how to do your custom repeating directives, how to do transclusion correctly, and all the way from variations on that, how to work effectively with services, and cover directives really comprehensively. And that should be out in around a month. So sometime around the first November maybe a little bit after that. So that's my pick.

CHUCK:

Do you have a tip?

JOE:

Yeah. Keep your eyes out on Angular 1.3, because there's a lot of cool things coming up and they are changing a few things. So if you get time, go and read the release notes for Angular 1.3. And I'll put them in the show notes.

CHUCK:

All right, Lukas do you have a pick and a tip for us?

LUKAS:

One of my favorite programming books is Clean Code by Robert C. Martin, aka “Uncle Bob”.

JOE:

Oh my gosh, I love you for saying that, Lukas.

LUKAS:

Yes. When I read it, it just kind of crystalized everything I want it to be. He’s a craftsman. And I use that one very specifically. If you’ve read that book, you'll understand why, is I just try to pick it up every so often and just kind of go through it. I think it's really one of the most important programming books that I know of that I've ever read. So Clean Code by Robert C. Martin. If you haven’t read it, go read it. If you have read it, read it again.

And I have two tips around directives. One is when you declare a directive, it will be in camel case, but when you actually embed it into your HTML, Angular automatically converts that into a snake case. And so for instance, if you did like “MyDirective”, when you declare it to your HTML, it will be “my-directive”. I've been bit by that a few times. Camel case gets converted into snake case.

And one more best practice, is in the link function, you do get a scope object. I really recommend to not put your imperative logic in the length function, but actually separate that back out into the controller, because the controller and the link function shares the same scope object, but really try to keep that in the controller, it just makes it easier to test.

JOE:

Those are awesome pieces of advice, Lukas. The snake case thing still bites me up to these days sometimes. It's so easy to forget.

CHUCK:

My pick. My iPhone had some problems, and there's a store out here I guess they are spread very far and wide, called Simply Mac. And I took my iPhone in there, told them I was having battery problems. It turns out there was a recall on the iPhone 5, so if your battery lasts not as long as it should, then you can go check and see if it's eligible for battery replacements. So I had my battery replaced for free and it made me happy. So I'm going to pick that.

And then I'm just going to plug, I have a lot of asking a lot about podcasting, so if you go to pickuppodcasting.com, you can actually get my podcaster’s tools guide, and get signed up for the webinar that I'm going to be doing maybe this month, so check that out. And I don’t have an Angular tip. So Federico, go ahead.

FEDERICO:

Yeah, okay. I have two picks, the first one is a shameless self-promotion. I'm working on a project called TRecs. I'm making it my engineering thesis. And the idea is to make screencasts instead of using video as the backend, you use just text. It's implemented in Ruby. And I'm right now working on a JavaScript client. So I will put my link on the show notes.

And my other pick is, pair programming. I really love to pair program whenever I can. So I think it's a very, very good practice. So if any of you wants to pair with me on anything, I'm open to it. So those are my two picks.

I don’t have a tip because as I've said, I'm a newbie, but I’d like to use this space to tell something that really changed my view on Angular. Today, we talked about directives, and I don’t know what you said anything you can do in Angular… you said is directive or something like that. And something that really changed my view of Angular is ngApp is a directive. So yeah, Angular is built on Angular. So I know it's not a tip, but something that can make you see differently.

LUKAS:

Well said. That’s kind of the big punch line with Angular. It's like, “Hey, it's built on top of it.”

CHUCK:

Yeah that's really cool. I've never really thought of it that way.

FEDERICO:

Yeah, someone told me that, and it blew my mind.

LUKAS:

Can you say that one more time? Say, “It blew my mind”. I love that.

FEDERICO:

[Chuckles] It blew my mind.

LUKAS:

Yes!

JOE:

[Chuckles]

FEDERICO:

Now you're making me blush.

[Laughter]

FEDERICO:

You know the red button to cut the call out, well, that’s me right now.

JOE:

[Chuckles]

CHUCK:

All right. Thanks everyone for listening. We'll catch you all next week!

[This episode is sponsored by Mad Glory. You’ve been building software for a long time and sometimes it gets a little overwhelming; work piles up, hiring sucks, and it's hard to get projects out the door. Check out Mad Glory. They are a small shop with experience shipping big products. They're smart, dedicated, will augment your team, and work as hard as you do. Find them online at madglory.com or on Twitter at @madglory.]

[Hosting and bandwidth provided by The Blue Box Group. Check them out at bluebox.net]

[Bandwidth for this segment is provided by Cache Fly, the world’s fastest CDN. Deliver your content fast with Cache Fly. Visit cachefly.com to learn more.]

Album Art
012 AiA Directives
0:00
32:25
Playback Speed: