The Power of Structural Directives in Angular
What’s a Structural Directive?
A Structural directive changes the DOM layout by adding and removing DOM elements.
The two most common structural directives you’ll come across are ngIf
and ngFor
.
Understanding the asterisk
The asterisk is syntactic sugar for something a bit more complicated
Let’s take for example the ngIf
directive:
- Angular will wrap the
host
element with atemplate
tag. - Angular will transform the
ngIf
to be a property binding.
Create a Structural Directive
First, let’s understand how to create a structural directive. We are going to implement our simple copy of the ngIf
directive.
We can use our directive like this:
<div *myNgIf=”condition”></div>
Let’s explain what is happening piece by piece.
TemplateRef
— As the name suggest the TemplateRef
is just a reference to the template
.
ViewContainerRef
—
If you think about it, eventually templates contain DOM elements, so if you need to insert an element, you need a place to “put” it. In Angular, this place is called a container.ViewContainerRef
is a reference to the container.
Which element is the container in this case?
Angular will replace the template
with a diagnostic comment that will represent the container.
Let’s see this in action.
The code above will generate this output —
The ViewContainerRef
also exposes the createEmbeddedView()
method that takes a template
and renders its content as a sibling to the container. ( in our case the comment )
The final step is to create a setter as Input
and based on the condition to create/clear the template.
Now that you understand how to create a structural directive let’s see two real life examples.
Show Content Based on the User Role —
Imagine that you need to show/hide content based on the user role. Let’s say you have a user stream that will give you the current user and you want to determine if he has permission to see the content based on his role.
Note: authService.user
returns an observable.
The usage —
Very cool 😎 !
Create Range Directive —
You can see that in this case, we are passing the second parameter to the createEmbeddedView()
method. Angular 2 templates have a special let
syntax that allows you to define and pass a context
when they’re being generated.
This will allow us to reference the variable we declared back on the *range=”[20,30]; let num”
as local variable on that view. We use $implicit
because we don’t know what name the consumer will assign to it when he uses the directive. ( it’s like we use ngFor=”let todo of todos”
)
The second approach is to expose your context as keys that you defined, for example:
Now we can use our directive:
You can create more advanced directives like ngFor
but this is for another post.
Things to not miss:
Follow me on Medium or Twitter to read more about Angular, Vue and JS!