Learning Angular: Directives - Custom
I am continuing from my last Learning Angular
article. This
time, I write a custom directive using Angular’s documentation to
write a custom appUnless
directive to write my own: appFor2
- a
specialized for
directive.
By reading this article, you will understand how to create your own
directive and change an item in Angular’s TemplateRef
.
This article will take you less than five minutes to read.
Introduction
As I used ngFor
in my ngFor
article,
it annoyed me that I couldn’t not write the loop in this form:
Angular does not execute code past one level in the template,
(i.e. Object.keys(items)
is a string in the template) there needs to
be a temporary variable to hold the keys of items
.
In the Angular documentation, the document how to create your own directive, I thought: why not create a directive so it would be:
This should be easy, right?!
Starting with unless
Angular
documentation
shows how to make custom directive for the unless
function.
Cool, this is a good starting point as:
- it has the setup to create a new directive
- it’s similar to what I want to make
- not part of the ‘standard’ library
I’m basically halfway there!
Following Along
If you would like to follow along with this code, you can use the Github link to get a final copy of the code or view the project in your browser using this StackBlitz link.
Port unless
into my project
To get a better feel of whats going on, I translate the unless
function into my application along with its infrastructure. Everywhere
there is an unless
, I replace with For2
or its equivalent.
The app.module.ts
file:
The for2.directive.ts
file:
Without this example in the documentation, I would not have such an easy time setting up a custom directive in Angular.
appFor2
v.0
Instead of keeping the appFor2
function body the same as the
original unless
, I change the appFor2
function to the following:
- changing
condition: <boolean>
to:items: Array<any>
sets my function to accept an array of<any>
item instead of a boolean. - using
console.log("hi from appFor2");
validates the configuration through a simple message in the console.
Using appFor2
To use appFor2
, the app.component.html
file needs an entry, let’s
keep it simple and reuse the words
list from my ngFor
article:
Let’s run the application, open our browser and make sure things are working.
Nothing on the page, which in this case, is a good sign.
Let’s open the browser’s console and see if there’s anything:
Great - appFor2
sends a message to the console. This means we can
execute any code in appFor2
.
Let’s get a sweet for
function going!
Next Step
In the documentation, unless
had this code in it:
The this.viewContainer.createEmbeddedView(this.templateRef);
looks
important. Let’s add this to our appFor2
function in the following
manner:
Let’s run it and see what we get in our browser:
Interesting, there’s four bullets with nothing in them.
The fact that there are bullet points and not just “empty space” is
important. That means the viewContainer
has <li>
element details
and Angular passes them in through templateRef
.
How can the appFor2
function put the contents of the items array
into the viewContainer
to populate the bullet points?
Digging around
Honestly, I was looking around the Angular documentation with a hope I would find an article on working with TemplateRef. The documentation on TemplateRef did not have the details I wanted. I did find another article that pointed me the right direction!
The TemplateRef is an abstraction and designed so Angular can render into anything: different web browsers, mobile devices, native applications.
Digging through TemplateRef by outputting the object onto the console
using console.log(view)
let me interactively poke it.
I kept poking around until I found the textContent
entry, which the
above article mentions.
Let’s see if setting this textContent
value as: item
will do
anything using the following code:
Wow, that works!!!
Wait a minute…
That worked for a list, what if we use appFor2
in a paragraph? Like so:
Looking at the page, the result is:
Wow, that’s works too. I basically have a new implementation for for
the way I want, in a <ul>
, <p>
, and more.
Conclusion
Using the Angular documentation for creating a custom directive as a
basis, I created my own custom directive that is a for
loop, done
the way I want.
Finding the way to manage the TemplateRef was the hardest part and took trial and error.
I won’t go making my own custom for
loop every time I want to work
with a list of items. This exercise definitely gives me a little
understanding of what’s going on in TemplateRef and how display items.