Bindon: lesser known Angular template features
Angular 12 just came out which added a nullish coalescing operator (‘??’) to templates. But what are other features Angular templates have that you might have never heard of? Let’s find out!

Bindon: lesser known Angular template features
Angular 12 just came out which added a nullish coalescing operator (‘??’) to templates. But what are other features Angular templates have that you might have never heard of? Let’s find out!


Angular 12 just came out which added a nullish coalescing operator (‘??’) to templates. But what are other features Angular templates have that you might have never heard of? Let’s find out!
ngProjectAsLink to this section
Angular content projection is a bit like the Web Components slots system. While you can just write <ng-content></ng-content>
and everything you put inside your component tag would get projected there — you can also add multiple content tags with “select” attribute for targeted projection. Like the example below:
<>Copy@Component({ selector: 'layout', template: ` <ng-content select="header"></ng-content> <main> <ng-content select="aside"></ng-content> <ng-content></ng-content> </main> <ng-content select="footer"></ng-content> `, styles: [` :host { height: 100%; display: flex; flex-direction: column; } main { display: flex; flex: 1; } `] }) export class LayoutComponent {}
Now you can pass sections to this layout component with content projection:
<>Copy<layout> <header>Header</header> <aside>Sidebar</aside> <footer>Footer</footer> I am content </layout>
But what if you want to project a block of content without wrapping it into an actual DOM element? Like several tags to be projected into a single slot or project some plain text. You can use the ng-container
tag and mark it with ngProjectAs
. See example below:
https://stackblitz.com/edit/angular-content-selection
This was recently added to angular.io under content projection guide so if you want to know more, you definitely should read it!
ngNonBindableLink to this section
Let’s assume you want to show an example of interpolation with handlebars and display the following as is: <div>Hello, {{userName}}</div>
. But if you want to have actual handlebars in the template you need to escape them somehow. Otherwise Angular would think you try to process them. Try adding single ‘{‘ to the template. You will see the following message:
Do you have an unescaped "{" in your template? Use "{{ '{' }}") to escape it.
Writing 5 handlebars instead of one is suboptimal 🙂 You can try using a custom interpolation symbol for this component but this won’t work — this option doesn’t replace the original symbol, just adds an alternative.
This is where ngNonBindable
comes to the rescue. It’s a compiler directive (like i18n
) which tells Angular compiler to treat a section of template as plain html: <div ngNonBindable>Hello, {{userName}}</div>
ngPreserveWhitespacesLink to this section
As you might know, Angular saves you the troubles of unnecessary whitespace symbols in your templates by removing them during compilation. If you do not need that you can turn this off in angularCompilerOptions
of your tsconfig.json
for the whole project or in @Component decorator for a particular component. Generally this is a very helpful feature but sometimes you want to disable it for some specific sections. Another Angular compiler directive can help you with that — just put ngPreserveWhitespaces
on an element in your template and the compiler would leave all the whitespace intact.
&ngsp;Link to this section
Related to the previous block — non breaking space character is treated as a whitespace and can be removed by the compiler. If you want it to remain there’s a special symbol that came from Angular Dart believe it or not — &ngsp
. It survives whitespace purge and gets replaced by  
during compilation.
$any()Link to this section
Did you ever work with a 3rd party library that has type issues? Say you operate immutable data and want to feed your array to a component input. But the type is set to be an Array
even though there are no mutations allowed. TypeScript will tell you your readonly instance is missing a few mutable methods and throw an error at you. Or the interface might be written plain wrong if maintainer is not a TypeScript enthusiast 🙂 Here are two steps that you can take:
- Wrap your object with
$any()
special function:[value]=”$any(value)”
- Go to that 3rd party library GitHub and make a PR fixing the type
Don’t forget that it only works if both steps are taken! 😉
BindonLink to this section
Does this look hazy to you due to all the special characters?
<>Copy<my-component #component [@animation]=”animation” [value]=”value” [(banana)]=”twoWayBoundValue” (output)=”onOutput($event)” (click)=”onClick()” ></my-component>
There’s an alternative syntax to those binding and you can use it to write the same template without all those brackets:
<>Copy<my-component ref-component bind-animate-animation=”animation” bind-value=”value” bindon-banana=”twoWayBoundValue” on-output=”onOutput($event)” on-click=”onClick()” ></my-component>
Admittedly I’m not sure why you would want to do that. Maybe to easily sort bindings by their type? Anyway, you can do that so now you know how 🙂
BonusLink to this section
A small bonus — did you know there are other built-in tags you can use in Angular templates besides ng-template
, ng-container
and ng-content
? There’s also the ng-component
. It’s not a template feature per se, but I’ve seen it in DevTools while inspecting templates and was quite surprised to find it, so I’ll explain it in this article too.
Maybe you can guess for yourself why it appears in the HTML after Angular rendered the page? Here’s a small tip for you: selector is optional for @Component
decorator:
<>Copy@Component({ selector: 'app-root', ←---- this thing is optional ... })
So think about what Angular can use for components that don’t have this property defined. You probably guessed that it’s exactly where we can see ng-component
— it’s an auto-generated tag for components that are lacking selectors. How can components appear in HTML but not have a selector? Well, you might dynamically instantiate a component with *ngComponentOutlet
or the component can be inserted after router-outlet
by the Router
!
Do you know any other template special cases that are missing in this article? Be sure to drop them in comments because I have never seen a comprehensive list of those and this article is just what I gather from experience. Thank you for reading!
Comments (0)
Be the first to leave a comment
About the author

I’m a devoted Angular developer and a musician. I use one thing to help me not to starve while doing another and I love doing both. I work on Taiga UI at Tinkoff and I like sharing my findings.

About the author
Alex Inkin
I’m a devoted Angular developer and a musician. I use one thing to help me not to starve while doing another and I love doing both. I work on Taiga UI at Tinkoff and I like sharing my findings.
About the author

I’m a devoted Angular developer and a musician. I use one thing to help me not to starve while doing another and I love doing both. I work on Taiga UI at Tinkoff and I like sharing my findings.