Advanced Patterns with Angular Directives - AiA 379
Armen, Lucas, and Subrat join this week's episode to talk about "Superpowers with Directives and Dependency Injection". Armen begins the show by talking about the reason why he thinks directives are one of the most crucial tools in Angular. They also discuss the powerful use cases for Directives.
Show Notes
Armen, Lucas, and Subrat join this week's episode to talk about "Superpowers with Directives and Dependency Injection". Armen begins the show by talking about the reason why he thinks directives are one of the most crucial tools in Angular. They also discuss the powerful use cases for Directives.
Sponsors
- Chuck's Resume Template
- Raygun - Application Monitoring For Web & Mobile Apps
- Developer Book Club starting
Promoted Links
- Unvoid Connector Program - You connect us with potential clients and we pay you up to 10.000 USD per client
- Unvoid - Angular Experts - Design and web development services with enormous expertise in Angular for companies that truly care about quality
- Superpowers with Directives and Dependency Injection
Social Media
Unvoid
Lucas Paganini
- YouTube @lucaspaganiniweb
- LinkedIn @lucaspaganiniweb
- Twitter @lucaspaganini
- Instagram @lucaspaganini
- TikTok @lucaspaganiniweb
Armen Vardanyan
Subrat Mishra
Picks
- Armen - Ivan Vasilievich: Back to the Future
- Lucas - Super Pumped: The Battle for Uber
- Subrat - The 80/20 Principle
Transcript
Lucas_Paganini:
Hey, welcome to Adventures in Angular, the podcast where we keep you updated on all things Angular related. This show is produced by two companies, Top End Devs and Unvoid. Top End Devs is where we create top-end devs to get top-end pay and recognition while working on interesting problems and making meaningful community contributions. And Unvoid, which offers remote design and web development services with specialization in Angular for companies that truly care about quality. In today's episode, we'll talk about Angular directives. Don't knock yet! think this is too basic, but that's exactly what we want to dismissify today. Directives are super powerful and heavily underutilized. In today's show, we will show you powerful use cases for directives. My name is Lucas Paganini. I'm the CEO of Envoyed and your host in the podcast. Joining me in today's episode is Armin Vardanian.
Armen_Vardanyan:
Hey everyone.
Lucas_Paganini:
and Subrat Misha.
Subrat_Mishra:
Hello.
Lucas_Paganini:
All right, so Armin, you are going to be the star of the show today because Armin wrote a series of articles about how to use the full potential of directives in Angular. And we will be picking out examples from the articles that Armin wrote. So we will be leaving links to the articles in the show description. I encourage all of you to, before to after the show, go take a look at the articles there because they are super well written and the examples are really good so they definitely deserve as much recognition as they can get. So Armin could you introduce the audience about in which ways you think directives are underutilized and then we can start from there?
Armen_Vardanyan:
Yeah, sure. First of all, thanks Lucas for promoting my articles way better than I do. So I always knew that directives are one of the important tools in Angular. But actually, during writing these articles, I also learned a lot about how we can use them to generally simplify templates. That's their main purpose. Templates are the hard part in Angular. Usually, the code isn't always that understandable. There's lots of boilerplate, like tags, closing tags. attributes, some stuff that you don't really need, some stuff that kinda doesn't allow you to read the code that clearly. And on top of that, we now have the template syntax, we have components, new HTML elements, more nesting, bindings, event bindings, and so on. So usually templates are the place where most of the mess is going on. We focus a lot on the class part of a component, for example, where we write the actual logic, but there's lots of logic going on in template 2. So, one of the first things you learn when you begin with Angular is something like the ng-if directive, right? And the documentation will tell you that this is like writing an if statement and it will change based on its input, it will show or hide the element, it will remove it from the structural directive which is something, something, something, and lots of people don't really know what a structural directive is, what's the difference and so on. But the reality is is that beyond the native, let's say, directive that we have, we have like five or six, I guess, there is a huge number of use cases where you can solve your problem, you can make your code more reusable, you can make something more composable, especially with the new APIs, just using a directive instead of whatever you're trying to do right now. Sometimes directives kind of replace components. Sometimes you don't really need a component or you don't need to directly drop the component in template for it to work. Sometimes you need to communicate between components and when we say communicate between components, what we usually mean is that like, you know, observables, but you really can do that with directives too. Or I don't know, you need some very local logic on some piece of template and most of the times it just goes to be some logic that either going to be copy pasted. Maybe someone will try to extract that logic to a service, apply that logic, but you can really apply this part to the business logic. If you're doing some business logic, I don't know. I don't know, loading some data and so on, which is a part of business logic. But the actual DOM rendering, DOM showing and so on, parts, you don't really want the service to do that, right? So lots of people opt in for components and that is understandable. Components are a good tool, obviously. But I believe that Angular is built on directives more than it is built on components. you're not going to obviously have lots of components. You can have one component and just inside of it you can build anything you want. But you're going to use lots of different directives and every single one of them is going to do some particular thing that is super usable and is super useful in that context. So today I really want to focus on advanced use cases on situations where can be simplified, made more reusable with directives and situations where we can sort of use different tricks that directives have, because lots of people don't know about the small tricks, we're gonna talk about it. So I think we can just go on chronologically, because each article focuses on one aspect of directives and see how it goes.
Lucas_Paganini:
That works. I would like us to start from bringing the use cases that you brought on your articles,
Armen_Vardanyan:
Yeah.
Lucas_Paganini:
because I think by tackling the use cases, it makes it so much clearer when you can use a directive, because I think the biggest problem that Angular developers have with when they should use a directive is exactly that they don't know when a logic can be isolated in a directive level. And most times they think, So by bringing those examples, I think we can start dismissifying that. So yeah, let's start with the first one. What is the first use case, Armen?
Armen_Vardanyan:
I absolutely agree with this approach. I want to try to give each of these article examples a sort of generic name so people have more familiarity when they kind of discover these use cases in their own code bases, right? So I want for people after reading these articles, after listening to this podcast, I want them to see in their code that, oh, you know, this is one of those use cases. Maybe a directive would help here. So let's start with the first one. I think the first example of what the directive can achieve is I have this HTML element, for example, that has some specific properties, like an input that is not just a block or something. And I want to build something on top of it. So my example that I use in the article is a password strength meter. something, we want to show them a bar or I don't know a score or whatever, right? The details are not important but what is important that we have a password input and around it kind of this local area in the template we want to build some logic but we really don't want to put that logic in this parent component in the host component we don't want it there because well who knows maybe we have several password, several pages that contain password inputs and some and for example, we have a registration page that has like two passwords, like password and a confirmed password. So we really want to be as precise as we want to repeat that code and so on. So one first instinct might be to maybe write a component that will wrap around an input tag, right? And then do everything inside of it. So that is not bad. obviously, but components are a more strong sort of coupling, right? If I put, like, basic example, if I put my input in a component, that's okay, but what if in some other place I need really different styling for this input? Or I don't know, I need to add some property or add another directive on top of it on some other place. That could be a problem. content projection but then I cannot make my component to be a control value accessor by itself. Maybe I want to do a validation on it inside of it then the connection would be lost it would be a mess right and even if I do make it into control value accessor that would mean the component will just grow large right. So what I can do instead I can write a simple directive that will bind automatically to all password inputs. I can do that with the selector. So the first misconception that we're kind of busting here is that you need to put an attribute on an element so it will work. That's not true. The selector of AngularDirects is very powerful. You can bind to html elements directly. So you can write a directive that works on all div elements. You can bind to an attribute that is used case like the most useful example but obviously the other are useful too. We can bind even to a CSS class in an Angular directive. We can say if this element has, I don't know,.happy class for example we can add some stuff. I don't know. That's a stupid use case obviously but who knows maybe you're doing something with the CSS and then you want to add some actual JS I never did that, but it is possible. So in this case, we are binding to all password inputs, the input type password, and what we are doing here is what we want is for it to be super customizable, right? We don't want the directive itself to actually write something or create a component and append it somewhere. We can possibly want that in other examples, but here we to kind of take an input in the template and understand how strong is the password that the user wrote there. So to achieve that we just use the export as functionality of the directive. Export as is a piece of metadata that you can put on in the directive decorator. It gets a string which is essentially the name of the component. In this case we can name it a allows us to extract the reference to the directive instance in the template. So if directive has some state or some method or whatever, you can call it in a template, you can access it in the template and just use it. So if we just bind to the input, calculate the password strength when, I don't know, the user types, we can do it with host listener or something, then we can just store it property, like we have a strength property on the directive and that's it. And that's it. Then in the template where we want to use it, we can just drop a local variable on this element, on the password input with the hashtag symbol. I don't know how to say that symbol. I don't know, I call it the hashtag symbol. Is it the hash? Is it the
Subrat_Mishra:
Yeah,
Armen_Vardanyan:
hash?
Subrat_Mishra:
or bound, maybe.
Armen_Vardanyan:
Yeah. You can name a local variable and get the reference to this particular input's password directive. Sounds a bit complicated. It's simpler than that. You just get the reference to the component class instance. And now you can just do the password meter dot strength, or I don't know, if you named the variable X, you can just do X dot strength and you have it. Now in the template, you can do whatever you want with it. You can customize it. The input remains a simple password input. It's not wrapped into anything. If there is just a bit of functionality added on its top, which we can access elsewhere to build, I don't know, we can build an ng-switch somewhere and just say, oh your password is weak, or I don't know, your password is medium strength, or it's strong, or whatever. So it doesn't impose anything, it's super customizable, and so on. It would cause no problem and it automatically binds to those inputs. If you don't want it to be bound to whatever particular input, in that you either can add an input property, like I don't know, no password check or whatever, but an easier way would be to just use the selector itself because actually in the Angular directive selectors you can also use the CSS not like pseudo class or how they call it and just say not and some property, for example, not check and then just drop a not check on any input and directly won't work on it, it won't even start working on it. to write if statements inside your code, like if this is working, then do this logic and so on. You can further customize it. You can use directives together with dependency injection. And we do that, the series of the article is actually called Superpowers, the Directive and Dependency Injection. So in this particular example, we use dependency injection to get a function that the user can provide. When I say the user, I mean the developer, the user's directive. that uses this directive, they can provide a function that does the checking. Maybe they need a custom checking. Some may be satisfied with just checking like the length of the password is long, then it's strong in my book. But some other people may want to validate it against the regex. So if we want it to work globally, we don't want to provide this function via an input every time, right? So we can just use a we declare a provider function that the user can give their own function as an argument and then the directive will just automatically know that I'm gonna use this function. We went a bit further there with the DI stuff, we made it so it like we could provide it with an input if we want for this one particular input element to work differently than all the others and so on but I think we're talking more about directives I'm not gonna go too deep into that. I just mean that with the dependency injections, you can always provide configurations to your directive and that is a super cool thing to have.
Lucas_Paganini:
Nice. Before we go on to
Armen_Vardanyan:
you
Lucas_Paganini:
more use cases, I would like to expand a bit on some of the things that you mentioned in this use case, which I thought were most relevant to Angular developers. So the highlight of this first use case is, at least to me, definitely the power of selectors. The fact that you can select what gets, an instance of the directive by not just using attribute selectors. And I think that one way that the audience can maybe click on that and understand it is imagine that you're doing document.querySelector or querySelectorAll to find all elements that match a given querySelector. The string that you're is the same that you can put in a directive selector. So I am really unsure if there's any limitation on Angular side in that sense of how much of the query selector syntax is supported, because I actually believe that it's just using the same logic that the browser uses to select an element. And thus, you can apply a directive to elements like Armen was saying. So the same way that you can do document query selector and find elements based on a class, you can also apply a directive based on a class. You can also do it based on a tag. So for example, you can apply it to all inputs or inputs of type password. And this way you would be able to apply your password string directive to all inputs without needing to add another attribute. with that. Like literally, you could use... I am afraid of saying everything, but almost everything that would work in document-party-selector you could use in a directive selector. Maybe it's everything would work in both scenarios, but I haven't tested all of them to make sure and I don't know how the
Armen_Vardanyan:
I have.
Lucas_Paganini:
source code of Angular works. So does it work, Armin? Like can you use everything?
Armen_Vardanyan:
No, there are limitations, it's not the same. Well, the first and most obvious limitation is obviously like you can't build a dynamic query. You just put it statically and you can't depend on a config, on a condition, you need to do that all that logic in the directive, which is okay. It's not that bad, but you can't really use all the types of CSS selections. Like you cannot select a child of something. Okay, you cannot apply that in an Angular directive. You can't say I'm gonna work on all the elements that are descendant of a div that has a class that has something. You can do a div that has a class. You need to particularly target an element. You cannot target an element in relation to other elements and that is a bit, you know, limiting. It doesn't, if you dive deeper and we understand how directives are applied, they are not applied with document query selector. Because, well, first of all, when they get rendered, you can't really know in what context you are rendering it. Maybe you're rendering in a server, right? That's why we're using the renderer tool and so on and such. It's kind of like when our templates get translated to TypeScript and then to JavaScript there are specific functions that do all those commands in the compile time When it is being compiled to the JavaScript the angular compiler Already decides that oh, you know this element needs to be Possibly wrapped in the directive and it will put it there and will create the binding I mean it will create the code that will create the binding after that. Doing like ancestor or relational checkings that wouldn't fly in the compile time at all, I guess. Maybe there could be other approaches, but for example, like in AngularJS, I believe you could do like some weird stuff like that, but I think it's not a big limitation. I mean, how many times do you really need to run logic on based on a relation of HTML elements. And anyway, if you want some sort of relation, you can create two directives, a child and a parent. Imagine how form group works together with form control name, right? You write a form tag, for example, you put the form group and a reference to your form as an input and then inside of that form element you can just say form name of that control, right? They interoperate together. They can inject, they use dependency injection under the hood to work on all of that. I will probably cover that in the sixth part. I was thinking about it today. I was wondering how from control name specifically works, because it needs to be a child of the form group and they need to kind of understand. Yeah, they use dependency injection under the hood to handle that. So it's still possible, but still very powerful, you can achieve lots of stuff with them. So I guess this is the first step when people who already know Angular work with Angular. This is the first step of understanding that, oh, you know, I am actually realizing that there's more of it with directive. This is the first step to being like a directive expert. The selectors is the first step. You need to know that there are more possibilities of that.
Subrat_Mishra:
Yeah, I think as you are saying about the form group, one thing may come into my mind is the most use case of what we're discussing now will be maybe instead of having only a password strength, people will always check like in the same directive you can also check all the password possibilities yours company allows like maybe the some special character or I think that all things or like here we are checking for maybe in your article you are checking I guess for six or eight length the length would be six or ten and all those things and we can also check the characters and number of amounts. So one question coming to my mind which while you and Lucas are discussing about having a regex on the selector or same like query parameter. just nitpicking but will it affects a compile time a bit if you are going with a normal directive way, normal directive name without like a input type password or input type text or something. So have you like just gone through any how much time it may be in milliseconds but I'm just curious like how Angular decide it need
Armen_Vardanyan:
Um
Subrat_Mishra:
to go through all the input and check type and apply on them.
Armen_Vardanyan:
That's a really good question, actually. What I imagine is, the thing is, with the directive, it's kind of reversed.
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
You're not, when Angular compiled it to the actual JavaScript code, the advantage that you have in that situation is when you use document query selector, if you're selecting with an ID, it's
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
way faster than selecting
Subrat_Mishra:
I see,
Armen_Vardanyan:
with
Subrat_Mishra:
yeah.
Armen_Vardanyan:
a class name because it's gonna go through the entire tree
Subrat_Mishra:
Yeah.
Armen_Vardanyan:
and so on, and it would be harder if there is something like I want to select all the inputs of type text that have this class and so on that will be even longer, take even longer.
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
Because in this situation, you have the document, right? And you say, go find somewhere something and you have lots of HTML elements, right? But with the Angular rendering, how it works and how it applies directive is the reverse. You have the elements and you need to check applies to some directive and you have like five directives for example
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
in a given context
Subrat_Mishra:
Yeah.
Armen_Vardanyan:
especially with standalone when you directly import the you imported one directive you just check if it binds to this one right so it's
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
a linear check and you just need to check this this this this is element and like that's it so I don't think more complex selectors would be of any significance the checking would be like, it would need to perform like three more direct reference checks, for example. But that's a matter of one or two milliseconds, I guess.
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
And I don't think it will give any noticeable changes. In AngularJS, I remember distinctly that if you had the directive that could like bump into lots of elements, because everything in AngularJS was in runtime, then it would be like, entire DOM tree and find, I don't know, elements that maybe match some of my maybe directives. When I'm registering a directive, that means I'm going through the entire thing and seeing whether something sticks. But here we have the compiler and during the compile time it builds in a way that it will possibly know that this element could apply. It will create the code then during the
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
to check it, it will know what bindings it has and so on and so on. So yeah, I think the answer is that there is no significant difference.
Subrat_Mishra:
Yeah, I think it makes sense. If it is going in the reverse way, that means it has a map of
Armen_Vardanyan:
Yeah.
Subrat_Mishra:
input type password. We'll go to destetactive and just apply. Yeah, makes sense. I think the same will also happen in the SSR, right? In the server-side rendering. I think it
Armen_Vardanyan:
Yeah, I
Subrat_Mishra:
will
Armen_Vardanyan:
guess so.
Subrat_Mishra:
compile and just do,
Armen_Vardanyan:
Yeah,
Subrat_Mishra:
yeah,
Armen_Vardanyan:
I guess so.
Subrat_Mishra:
got it.
Lucas_Paganini:
Cool,
Armen_Vardanyan:
Ready
Lucas_Paganini:
okay.
Armen_Vardanyan:
to move to the next one?
Lucas_Paganini:
Yeah, yeah, definitely, let's do it. What's the next use case?
Armen_Vardanyan:
Yeah, I love the next one because of the magic that template refs and view container refs in Angular have. I really love it. I love it how it makes templates so much simpler. So the idea behind this use case is that you don't really need components in the situations where you need to change something in the template structurally. Well, we have structural directives Lots of people aren't very familiar with them. We just know that, you know, NG for the structural derivative and so on. But the real power comes is when you kind of insert the component somewhere in your template and even wrap it around some template that you have and make it work without having to write lots of like nestings in your HTML and so on. So the example that I'm using in this article We sort of have the situation where we want to display a loading spinner somewhere. And it could be on any element. So maybe one block, there's a button, if the user clicks on that button, there is an HTTP request. And we want to show loading and we want to block that part of the page, so the user doesn't click other buttons or, I don't know, other links. is really related only to this component, right? So how do we do that? How do we create a reusable thing? So obviously we have to build some component for that. We need to build, we can build a loader component. We will pass it an input, which will say true or false, right? And it will have content projection. It will have ng-content, which we'll put inside some, I don't know, some divs, and then based on input, it will either show this spinner and block the element or not. So that's great, that's not bad, that's not problematic at all, but if you have lots of different elements that can have access to this feature, this loading spinners, your template will become harder to read. You will have these large components that have like six, seven, eight levels of nesting of HTML tags and then you're adding on top of it like another, I don't know, app loader and maybe inside of it you also have some smaller block that can itself have its spinner in some cases then you're adding another level of nesting. In general, you know, if you're adding a component that has content it means you're tag or adding a closing tag. But in reality, we're not doing anything component-ish, right? We're just adding some modification to an existing piece of template. We just say, oh, this part of template can be closed with CSS or whatever, or a spinner can appear there. It's not a real, like, component stuff. it's true over this div or this span or this I don't know block or this maybe other component then it will just show the loading spinner over it right so if you already have the loading component it will just take several small steps to just turn it into a directive rather building a directive that utilizes this component and just glue it together through the template and there we use structural directives so structural directives are the ones that have access where it is being invoked. With this asterisk notation, we get an ing template, and then we have the directive, we can inject the template reference, template ref. So now we have the template, we just need to take this template, put this into the loading component, and then put this whole structure back where it came from. So of course we can do create component now, we can then create the loading component, we have the template, two steps remain. How do we give this template to the component? Well, when creating a component via viewContainerRef.createComponent, right, we have this function to create a dynamic component. You can pass it a reference to the root node of this ngTemplate that you have. So now your template magically appears inside the It's just actually just crazy, just two lines of code. You create a component and you add projectable nodes. There's this option. And then you give it a template ref.root node. And that's it. You now have this loading component with the template that came from wherever. Then there's this last line of code where we add the component with the create embedded view. Right? We sort of send it back now. So whenever on any element now with this directive, we can drop asterisk loading equals true or false or whatever. And it will just show that component wrapped on top of template that you have on top of that element that you're using the directive. So this can apply in lots of our scenarios. You want to make it, where you have simple content projection, you can turn it into a directive and your error template will become simpler. Don't use it in situations when your child component that receives the projected content is doing some heavy lifting. Like if you are building a tabs component, for example, that receives the child tabs and renders them and with just a component because directly would make it really messy. And what constitutes a tab or now is really weird. You don't want some tabs to be spans and other tabs to be divs and so on. But if you are just adding a functionality that is related to DOM on top of existing templates, then it's really advisable to just create a structural directive. Well, here you go, you can do that. And it's a really powerful thing. It will come up like in later use cases when you can dynamically create a component. If you can dynamically create a component, you can use a directive. Like on top of my head, like I have this component and I always want to append it with another component. So instead of going copy pasting that component everywhere like I don't know, I have a custom input and after that I want an error list component, for example, I always wanted to be there. I don't need to copy paste that component everywhere. I can edit it anytime that I encounter the selector of this other component. I can also use component selectors as selectors for directives that makes them extra powerful. I can select all the, I don't know, custom input components and add an error list component to it. That's it. I don't need to write it in a template. So yeah, it's kind of a really powerful tool if you think about it.
Lucas_Paganini:
Yeah, I like that.
Armen_Vardanyan:
you
Lucas_Paganini:
We had a recent episode where we talked about structural directives. It gets pretty tricky to explain it in a podcast format, but once you look at the code, it sounds way simpler, right? So I like how you mentioned this in the articles because most developers, they don't know that they can create directives with the asterisk in front of them. A lot of developers think that this is like the mark of an Angular native directive. Well, up until the point where they actually use a third-party library that has this asterisk in front, and then they're like, wait, what? But yeah, you can create those directives, and they give you a lot more power because, as Armen was saying, you are able to dynamically decide when to render the template of that structural directive. And you can also render it multiple times, which is the case of ng4. And that allows you to do so many powerful things. Like the example here was a loading directive. But you could do so much more. For example, I once implemented a tab structure. So I had an application which inside of it, there was a page that needed to have multiple tabs. So it had like an editor. you should be able to have many tabs. So how did I organize my code to support this tab functionality? I use structural directives. So I would have a directive which would be tab, and I would use that directive in the element that would declare the default template of a tab and this directive would also inject that would go into that tab, and then I could render, I could reference that data from inside the template. So there are so many use cases for structural directives. They are extremely powerful. So I highly encourage everyone to take a closer look on that feature of Angular
Armen_Vardanyan:
Hmm.
Lucas_Paganini:
and see how you can reuse your code by using structural directives.
Armen_Vardanyan:
You know, just
Subrat_Mishra:
it.
Armen_Vardanyan:
another example, again, it just came up in my mind from our current project. We build, we use Angular material and we build tables a lot. So we build a reusable table component. I don't go into details. It takes a list of columns that are some particular models and just renders everything. But if you need custom content, you can project ng-templates there. And you can also give it a dynamic header. And there is a header, there is a footer, and there is a search bar, and all of them can be custom. So how do you explain to the component that this is that and this is this, right? You use a structural directive. There is a table header directive, there is a table footer directive, you just drop it on an element, and now its parent component knows where to place them, where to put them, how to work with them, them and so on. So yeah, use cases are limitless with this.
Subrat_Mishra:
Yeah, I think it's a pretty pretty good example as you mentioned on table. I remember I have used a pretty simple use case like we have a dashboard which has lots of tables so what we have done is if there is no data I will just display text like there is no data or please change some condition to render the data so it need not need to go and put it in every table as if condition and just
Armen_Vardanyan:
Yeah.
Subrat_Mishra:
put a directive and just append the text if the data is empty or zero.
Armen_Vardanyan:
Yeah, that's exactly
Subrat_Mishra:
player
Armen_Vardanyan:
it.
Subrat_Mishra:
use case.
Armen_Vardanyan:
What do you think? Let's move to the next use case. That's the one that you liked.
Lucas_Paganini:
Yeah, we could talk about this for a very long time, but we should definitely move to the other ones. There's so
Armen_Vardanyan:
Yeah,
Lucas_Paganini:
much here.
Armen_Vardanyan:
that's the one that you liked a lot and I also enjoyed this. So as I already mentioned, you can also use component selectors as selectors for the directive. So if you have, I don't know, x component, a component that has like fx or whatever you call it, you can drop the same selector for a directive and that directive will work on all the component instances that it receives in the templates, wherever in your app. So initially it might be confusing like why do I need to select components? What I'm gonna do with them? Well, you can inject the reference of that component in your directive and that's a cool thing. Now you've got a reference to that component so you can play with it in this directive. It becomes really cool if you like third party components. Like you have this, I don't know, drop down or. I don't know. some other component from a library. And the example that really stuck with me is we're using PrimeNG and PrimeNG has a calendar. Like, it's like a date picker, but they call it calendar. So it receives a huge load of inputs. Like you can customize everything in it. Like the year start, year end, year range, range through, max range, I don't know, so on and so on. And when the business requirements complicated, you end up passing lots of those inputs to the component because all of them have been customized and don't match the default values, right? And the code becomes a real mess. Like, you put six calendars in a page and each one is like, you need ten lines because you have lots of inputs, so put them, everyone, on a new line, which is cool. So now you've got like 60 lines of code and So again, you could mitigate this problem if you started like wrapping all the third party components in your custom wrappers, but that won't be a good thing. You will end up sort of like maintaining the child component itself all the time. What you really want is to kind of like hijack component and say, you know, I want you to behave slightly differently. You can do that. So what we did with the calendar and I want to mention that it wasn't really my idea. I read about it in an article by Tim Dashriver. I will also put a link to that article because that was a big inspiration for me to kind of start investigating this whole directive thing. So the idea was you put the selector of P calendar, that's how it's called, that's its selector, you inject calendar if you're working with it. And the constructor, you just set your own default values. You just sort of, you come through between your template and the third-party component, say, you know, these are the default values, don't use the ones that you have. You just, you know, imperatively set new values. Or, I don't know, call a method that it has. We also had a directive that sort in PrimeNG because it didn't run, it changed detection cycle or whatever and it didn't check for a numerical input in some of its components. So it resulted in a bug. So we just hijacked that component and said, you know, if this happens, whatever, in our app, do this. The thing that you're not reacting to automatically will make you react to it with a directive. And you add zero code You don't need to customize anything other than, you just drop the directive, it works. Okay, if you want customization, again, you can go for selector. In Tim's article, you have like really crazy use cases, for example, he also used prime ng, so you have a p dropdown, it's just the usual dropdown. So what he did, when you add the property countries on it, it will automatically go download the list of countries and put it inside the drop-down and you don't need to do anything about it. And if you think about it, it's really crazy. If you are building something around a element, I'm trying to give a recommendation, right? If you have an element that you can use with ngModel, right? Be it an input, be it a custom having the same pattern of logic everywhere. For example, this exact thing with the countries. Maybe you have lots of pages where people need to select a country to see something or submit a form, right? You might think, I don't want to copy paste all of this country loading and displaying logic in all those components. You might think, oh, let's build a country's component that will show the drop down. But you have the problem, you now need to make that value accessor and so on. But in reality what you just wanted was to edit this list of countries to the to the drop-down. You didn't really render any new HTML, you didn't really do anything. So why not solve this problem with the directive? Okay, just make the directive, load that data and display. Okay, or maybe not load it, but I don't know, show it from the store if you're using something like ngRx, ngAccessor. You have a special service for this, whatever business logic, you just Google them together, okay, using a directive selector and so on. So that really makes, it really makes both your templates simpler and even your component like TypeScript code simpler. Just don't copy paste. Some would say, oh let's extract it to NGRX. Yeah, that's part of the solution. You still need to select the data, test the data, you can just skip that. If you have this reusable case, if you have this recurring case, so that's a recommendation. That's a pattern. If you notice that pattern, then maybe you can apply a directive and solve it.
Lucas_Paganini:
Awesome. So basically, let's recap the central message of the three things that we mentioned this far. So the first one was about leveraging directive selectors. The second was about leveraging structural directives. And now we're talking about, again, the selectors, but in a way that you don't... That you reapply the selectors to something that maybe already a selector. So maybe you already have a component which has that selector and then you create the directive that also has the same selector and then you don't have to add an unnecessary attribute. You're just adding a directive to all the components too, which I suppose that you could also do that by using host directives, but there are use cases where this would go beyond just and etc. So cool.
Armen_Vardanyan:
If you want to, there's a thing, if you want, like say you have a directive, a third party, that has a specific selector, okay, it's an attribute, that's it. And you want
Subrat_Mishra:
you
Armen_Vardanyan:
it applied to all, I don't know, tab components. You can do it in like five lines of code. You write a directive that selects all the tabs and add the other directive as a host directive. That's it. the selector and host director the other one will be added and that's it. If you want to interject something yeah you can write some other logic in the directive but you can even with the empty there just with the directive decorator you can find this directive from somewhere to this component somewhere and that sounds like crazy.
Lucas_Paganini:
Definitely. Sorry, Subrat, I think you were going to say something.
Subrat_Mishra:
Yeah, so I was just thinking, I think, if someone is listening till now, and one thing they could get from this podcast, like everything we are doing in Angular is possible in a directive. So if we just change our thought to do it in a directive, so how helpful it will be in the future, and just thinking of scalability. a switch of mindset will follow us on a good direction of having more directive, how we can achieve this scenario in a directive, how we can make it simplify using directive like as just Arman said, you can use a host directive and just truth line codes and it's done. You don't need to go and change it everywhere. I think this mindset will help a lot of people you can write a book on directive as well. You know in depth of that.
Armen_Vardanyan:
Yeah, I wouldn't wish so.
Subrat_Mishra:
Yeah, I think if someone can you have five series already you can add more and that eventually will become a book.
Armen_Vardanyan:
Yeah. Well, it is possible.
Lucas_Paganini:
Yeah, there are two more super powerful use cases that we still have to talk about. But I don't know if we should on this episode because this is getting way too long at this point. So perhaps we could do another part. But just to tease all of you, the next two would be using outputs also as selectors and also using directives for portals, so for projecting content in different parts of the application. So we can do that in another episode, but also you don't have to wait. You can just read the series that Armen wrote and the content will be there available right now. So if you're listening to this and you're like, You can, the link is in the description. And don't forget to leave a like on these posts because they were super well written. Again, Armin did an excellent job on that. And well, I honestly hate being the person that cuts things in the middle because I was also really enjoying the conversation and the topic. But is there anything that Subrath or Armin that you think we should mention this episode.
Armen_Vardanyan:
I think we should mention that the article series itself is not yet complete.
Lucas_Paganini:
Hmm.
Subrat_Mishra:
There are lots to come.
Armen_Vardanyan:
I have, no, I have like two entries. The other one will be about concretely implementing business logic concerns in directives, maybe as you said, like to tease a bit how you can build directives that check for permissions to show stuff without like explicitly calling for ngif And I think in the final one I will wrap up everything with a more in-depth example cases of selectors, like all the possible things with small examples and so on, so that everyone is on the same page with what we can and cannot do with the directive selector. So yeah, I guess that's important to mention too. Maybe and the seventh one is just wrapping up things so Maybe it is for the better to cut in the middle.
Lucas_Paganini:
Yeah, let's create this this tension. Dude, if you keep this up, like you should definitely do a book. I think people would pay to have that knowledge. That is so good. And it's such an advanced topic. So, yeah, thank you for sharing that, honestly. That's tremendous amount of work to do it and to share that for free. Like if whoever is listening to this episode, if you don't go read those articles, like I don't know what you're doing. They are for free and it's extremely valuable content. So yeah, do check the series
Armen_Vardanyan:
I don't
Lucas_Paganini:
that
Armen_Vardanyan:
like
Lucas_Paganini:
Armin
Armen_Vardanyan:
paywalls.
Lucas_Paganini:
is writing.
Armen_Vardanyan:
You know, I once wrote an article that turned out to be paywall. I didn't know that it was paywalls. It was way back in 2017, I guess, 2018. I wanted to share it with everyone, like at my job and so on. And everyone was like, it says you need a subscription to Medium. It wasn't Medium, it was the old days. I don't like
Lucas_Paganini:
Oh.
Armen_Vardanyan:
paywalls content. I have courses, right? Well, I co-authored most of the courses, so.
Lucas_Paganini:
At that
Armen_Vardanyan:
Yeah.
Lucas_Paganini:
moment, Medium automatically started putting your content behind a paywall and it wasn't
Armen_Vardanyan:
What?
Lucas_Paganini:
explicitly something that you were aware of?
Armen_Vardanyan:
I wrote for a publication. Someone
Lucas_Paganini:
Alright.
Armen_Vardanyan:
reached out and said, you know, you want this article to be on our publication? I was like, yeah, cool, why not? I didn't know that they were
Lucas_Paganini:
Oh,
Armen_Vardanyan:
paywalling it. Yeah, so
Lucas_Paganini:
gotcha,
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
after
Lucas_Paganini:
gotcha.
Armen_Vardanyan:
that I was like, no, I'm never doing this. A book maybe, okay,
Lucas_Paganini:
Thanks for watching!
Armen_Vardanyan:
but articles and blog posts and whatever will always be available for everyone.
Lucas_Paganini:
Yeah, that was shady. Yeah, that was a weird behavior because like imagine you doing the work for the publication and then they getting money on top of your work. That's so wrong, man. Yeah.
Armen_Vardanyan:
Yeah, sort of. Well, I mean, I think the model of the medium subscription was that if your article was payable, you automatically got money from medium. But you know, you need to write like a really big banger of an article to get something. Obviously, you weren't going to get a lot stuff writing about Angular because, I don't know, if 50,000 people read your article and it's more than I got on my most popular article. I think my most popular article got around like 35 000 readers, which sounds a lot, but like you know people writing about politics get like 7 million
Subrat_Mishra:
Yeah.
Armen_Vardanyan:
readers. Yeah, so you know.
Lucas_Paganini:
Yeah, that's a good point. All right. Okay, thank you. So let's start wrapping up and doing our promos then. So Subrat, let's start with you, man. How are you doing? What are you working on? Do you want to promote anything?
Subrat_Mishra:
Yeah, I think I am working on first of all on my channel. I think nowadays I'm a little bit busy on work and have started with some other projects as well. So not that focused on the frequency of my videos. I've just posted a video on model federation and then I'll continue with model So first I release a video of a series of video how we can expose microfontaine without using model federation like wrapping everything and just put it now it's time for how we can expose the functionality of application as a microfontaine and use that. So that's I think one thing I would like to say and hopefully the series will finish and I will put the videos. me luck.
Lucas_Paganini:
I wish you luck.
Subrat_Mishra:
Thanks.
Lucas_Paganini:
And yeah, as I was promoting Armand's content, I also think that you definitely deserve more people watching our content. You do such advanced videos. The other day, I was just browsing YouTube, and then your video was recommended about
Subrat_Mishra:
Mm-hmm.
Lucas_Paganini:
micro frontends. And I was like, oh, I'm actually interested in learning that. That was a really good video. So yeah, man, congrats on that. your efforts pay out and people recognize it.
Subrat_Mishra:
Yeah, like when Arman says, if you write a video on politics or music or comedy, you get tons of views. But with anything related to study, and our content needs to study, and then again needs to Angular. So it's like very few traffic. But yeah.
Lucas_Paganini:
What
Subrat_Mishra:
depends.
Lucas_Paganini:
about you, Armen? What would you like to promote?
Armen_Vardanyan:
I feel like this whole episode was a huge promotion of my content, so I'm gonna be humble and say, you know, nothing?
Lucas_Paganini:
Thanks for watching!
Armen_Vardanyan:
I don't know, what else can I promote? I'm working in enterprise. I don't have stuff to share.
Lucas_Paganini:
That's fair. I think that's a good argument. The entire episode was a big promotion. Which I'm very okay with. If all episodes get to be this way but we're talking about good content, I see no problem with it.
Armen_Vardanyan:
Hopefully it's helpful for people.
Lucas_Paganini:
It definitely will be. I think so. OK, so in my case, I am going to promote my company. But more specifically, I'm going to promote a program that we have for referencing clients to my company. So maybe you're aware of, but my company is specialized in web development with Angular. We are highly specialized in Angular-based projects. the developer that is listening to this, you are in an organization or you just know someone that needs help in an Angular-based project. It might be that they want to totally outsource the project or they simply want more Angular developers on their team to help with the project. So it might be project outsourcing or staff augmentation. No matter the format, you can recommend the client to us and get up to 10,000 US dollars. So I don't know. that's a good deal. If I were to recommend somebody to a company and they ended up closing and I get close to $10,000, I would be very happy. So if you're interested in that, if you're interested in learning more about this program, recommending someone, then go to unvoid.com slash refer clients to learn more. There's a link to this page in the show notes. So that's my promotion. And yeah, in terms of pics, I'll be honest, I don't have any pics for today's show. But what about you two? Armand, do you have any pics?
Armen_Vardanyan:
If you think about it, I'm gonna talk about some crazy stuff right now. So I was rewatching this movie and yeah, it's gonna be my pick. I watched it when I was a kid, several times. I used to love it. So I thought I can rewatch it. So I'm from Armenia, it's a post-Soviet country. So like old Soviet movies, both like Armenia and Russia and other, from the other post-Soviet even with the younger generation. Well, I am the younger generation, I wasn't born in the Soviet Union, so my parents were. So there is this Soviet comedy that is actually quite brilliant if you think about it. If you have read about the book the... I think in English they said The Master and Margarita. I don't know, it's quite a popular book. there have been even like Western movies on it. So the same writer has the short story that they made into comedic movie. And it's about time travel, but it's a Soviet movie. So it's kind of crazy. And it's about a dude who builds a time machine and goes back to like medieval Russia. And there is this guy who looks exactly like the Russian Tsar, they say or Ivan Grozny if you know how Russians call him and they switch places and there is this whole insane thing going on with people think that this guy who is actually some random dude from USSR is the Tsar and and there is the reverse thing going on in Moscow with the Tsar gets arrested and so on and people can't figure out why he's behaving like he's the most powerful guy I remember that I used to love it. If you're a history buff like me, I don't think you will learn anything new from it, but it's a really great comedy and I really enjoyed rewatching it. Every single line from that movie is sort of a meme, a quote, everyone who watched it remembers you said this and everyone else said oh yeah, you are from this movie. And the movie is called, well they translated it into English like Ivan Vasilevich Back to the Future, but that's kind of a stupid translation, I don't like it. If we go verbatim and say something like Ivan Vasilevich is changing his profession, you know, he used to be the Tsar and now he's just a random guy in the Soviet Union. If you like history or you for whatever weird reason if you're listening in the West like Soviet movies And haven't seen this one, but definitely give it a watch Yeah, that's gonna be my pick for today
Lucas_Paganini:
Cool.
Subrat_Mishra:
Alright,
Lucas_Paganini:
By the
Subrat_Mishra:
bye.
Lucas_Paganini:
way, sorry to cut you so
Subrat_Mishra:
Yeah,
Lucas_Paganini:
short, but
Subrat_Mishra:
go
Lucas_Paganini:
just
Subrat_Mishra:
ahead.
Lucas_Paganini:
to mention one quick thing. In the last episode, I mentioned Super Pumped was a series about the history of Uber and how it all started. But I was still in the middle of the series, so I didn't know if it was really that good. Just
Armen_Vardanyan:
Was it good?
Lucas_Paganini:
to... Yeah, yeah, I
Armen_Vardanyan:
Okay.
Lucas_Paganini:
think it is. I finished it. So if anyone was in doubt, thinking, oh, I don't know, Lucas just said that he watched the first episode. really good so yeah it's on Amazon so super pumped that's the name of the the show go ahead Subrat sorry to cut you
Subrat_Mishra:
Yeah, so you picked SuperPerm then. So you do have a pick this time also. So I think I will go the usual way of my, like I'll pick a book. I think it's a famous book, 80-20 Principle by Richard Koch. I think it mostly shows that 80% of work is done by 20% of things. I think it's a good mindset if you have overwork done with work you want to let go something then it helps you to decide and those things so I think Nowadays it's kind of happening the similar thing with me. So I'm just kind of having it in the similar situation so I'm just trying to Re-read that or re-listen that again, so thought to Share with you guys. So have a read if it is fine and if it help you to be common of by seeing the name 80-20 principle by okay you know that 80 percent of work were done by 20 percent thing I don't need to read a book but if you go inside the book then you learn a lot of how can be the mindset and how it will help you to decide on things that which those 20 percent things which will do your 80 percent work. So that was the big Yeah, for this week.
Lucas_Paganini:
Awesome, awesome. All right, I think that is it for today. Again, Subret, Armin, thank you so much for your time. We are all in different parts of the world, so the time is always terrible for
Subrat_Mishra:
Yeah.
Lucas_Paganini:
everyone in different ways. Like to me, it's exactly at lunch. For Armin, it's super late. For Subret, it's close to the work time. Like it's never great for no one. I highly appreciate you two taking the time to participate on the episode. So yeah, thanks.
Armen_Vardanyan:
I was happy to talk to you guys.
Subrat_Mishra:
Thank you guys, bye-bye.
Lucas_Paganini:
Bye.
Armen_Vardanyan:
Bye.
Advanced Patterns with Angular Directives - AiA 379
0:00
Playback Speed: