A structural directive in Angular is a directive applied to an <ng-template> that decides whether that template’s content renders, or how many times. The * prefix you see on *select is shorthand for that wrapper. For everyday conditions and loops, Angular now recommends the built-in @if, @for and @switch blocks. NgIf and NgFor are deprecated. This guide covers the mechanics, the decision between built-in blocks and a custom directive, and the migration path.
What a structural directive is
Angular’s structural directives guide says: “Structural directives are directives applied to an <ng-template> element that conditionally or repeatedly render the content of that <ng-template>.” An <ng-template> renders nothing by itself. The directive decides whether to create a view from it, and how many.
As an Amazon Associate I earn from qualifying purchases.
How the * shorthand maps to ng-template
When you write *select on an element, Angular creates an <ng-template> to host the directive and wraps the annotated element and its descendants inside it. The asterisk is not a special element. It is syntax sugar for the wrapper.
Free tools Windows power users keep installed
One-click scans. No signup required.
Microsyntax expansion
The string after the * packs directive inputs and template variables into a single attribute. Per the guide, *myDir="let item of items; index as i" expands into an <ng-template> that has:
#1 Best Overall
- the directive itself;
- a
let-itemcontext variable; - a
myDirOfinput bound toitems; - a variable
iexported from the template context asindex.
The key point is that the directive selector prefixes each key expression. The key of becomes the input myDirOf, so your directive must declare an input with exactly that name to receive it.
One structural directive per element
The shorthand corresponds to one <ng-template>, so an element can carry only one * directive. To combine behaviors, nest elements or add a grouping layer with <ng-container>, which adds no extra DOM element. See the ng-container guide.
Rank #2
Built-in control flow or a custom directive?
For routine conditions, loops and switching, use @if, @for and @switch. Write a custom structural directive when you need a reusable rendering rule those blocks don’t cover. The guide’s examples are gating content behind a permission check, and rendering a template once data from an external source arrives.
| Question | Leans toward |
|---|---|
| Is it an ordinary condition, iteration or switch? | Built-in @if / @for / @switch |
| Is it a domain-specific rule reused across many templates (permissions, async availability)? | Custom structural directive |
| Do you need to supply your own template context variables? | Custom directive |
| Do you need stronger template type narrowing than the built-ins give? | Custom directive with a template guard |
Are you replacing a deprecated NgIf or NgFor? |
Migrate to built-in blocks |
Building a custom structural directive
Two APIs do the work:
TemplateRefgives the directive access to the template it is attached to.ViewContainerRefrepresents the spot where the directive can create embedded views from that template.
The directive injects both, then creates or clears an embedded view when its input changes. Angular’s template type checker can also use template guards, which narrow input types and validate the template context, so templates using your directive get accurate type errors. Details and a full example are in the official guide.
Rank #3
NgIf and NgFor: deprecation status
The current API references mark both as deprecated since v20.0, pointing to @if and @for as replacements. The removal timelines differ, so don’t conflate them:
| Directive | Status | Removal intent |
|---|---|---|
NgIf |
Deprecated since v20.0; use @if |
A future major release, not named |
NgFor |
Deprecated since v20.0; use @for |
v22 (per the v20 API page) |
These details are version-sensitive, so check the linked API pages for your Angular version.
Rank #4
Migrating to built-in control flow
Built-in control flow has been available since v17. It is part of the template syntax, so it needs no CommonModule import. Angular provides a schematic to convert existing templates:
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteng generate @angular/core:control-flow
It can target a specific workspace path and can be configured to preserve formatting. See the control flow migration guide for the exact options. Review the diff afterward and run your tests, as with any automated code change.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




