Professional Documents
Culture Documents
Structural directives
Structural directives
Structural directive
shorthand
This guide is about structural directives and provides conceptual information on how such directives
work, how Angular interprets their shorthand syntax, and how to add template guard properties to One structural
directive per
catch template type errors.
element
Structural directives are directives which change the DOM layout by adding and removing DOM Creating a structural
element. directive
Testing the
Angular provides a set of built-in structural directives (such as NgIf , NgFor , NgSwitch and others)
directive
which are commonly used in all Angular projects. For more information see Built-in directives.
Structural directive
syntax reference
For the example application that this page describes, see the live example / download
How Angular
example. translates
shorthand
Shorthand
examples
This convention is shorthand that Angular interprets and converts into a longer form. Angular
transforms the asterisk in front of a structural directive into an <ng-template> that surrounds the
host element and its descendants.
For example, let's take the following code which uses an *ngIf to displays the hero's name if hero
exists:
src/app/app.component.html (asterisk)
Angular creates an <ng-template> element and applies the *ngIf directive onto it where it
becomes a property binding in square brackets, [ngIf] . The rest of the <div> , including its class
src/app/app.component.html (ngif-template)
<ng-template [ngIf]="hero">
<div class="name">{{hero.name}}</div>
</ng-template>
Note that Angular does not actually create a real <ng-template> element, but instead only renders
the <div> element.
The following example compares the shorthand use of the asterisk in *ngFor with the longhand
<ng-template> form:
src/app/app.component.html (inside-ngfor)
<div
*ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById"
[class.odd]="odd">
({{i}}) {{hero.name}}
</div>
Here, everything related to the ngFor structural directive is moved to the <ng-template> . All other
bindings and attributes on the element apply to the <div> element within the <ng-template> . Other
modi ers on the host element, in addition to the ngFor string, remain in place as the element moves
inside the <ng-template> . In this example, the [class.odd]="odd" stays on the <div> .
The let keyword declares a template input variable that you can reference within the template. The
input variables in this example are hero , i , and odd . The parser translates let hero , let i , and
let odd into variables named let-hero , let-i , and let-odd . The let-i and let-odd
variables become let i=index and let odd=odd . Angular sets i and odd to the current value of
the context's index and odd properties.
The parser applies PascalCase to all directives and pre xes them with the directive's attribute name,
such as ngFor. For example, the ngFor input properties, of and trackBy , map to ngForOf and
ngForTrackBy .
As the NgFor directive loops through the list, it sets and resets properties of its own context object.
These properties can include, but aren't limited to, index , odd , and a special property named
$implicit .
Angular sets let-hero to the value of the context's $implicit property, which NgFor has
initialized with the hero for the current iteration.
For more information, see the NgFor API and NgForOf API documentation.
Note that Angular's <ng-template> element de nes a template that doesn't render
The reason is simplicity. Structural directives can do complex things with the host element and its
descendants.
When two directives lay claim to the same host element, which one should take precedence?
Which should go rst, the NgIf or the NgFor ? Can the NgIf cancel the effect of the NgFor ? If so
(and it seems like it should be so), how should Angular generalize the ability to cancel for other
structural directives?
There are no easy answers to these questions. Prohibiting multiple structural directives makes them
moot. There's an easy solution for this use case: put the *ngIf on a container element that wraps the
*ngFor element. One or both elements can be an <ng-container> so that no extra DOM elements
are generated.
Following is the UnlessDirective selector, appUnless , applied to the paragraph element. When
condition is false , the browser displays the sentence.
src/app/app.component.html (appUnless-1)
1. Using the Angular CLI, run the following command, where unless is the name of the directive:
Angular creates the directive class and speci es the CSS selector, appUnless , that identi es the
directive in a template.
src/app/unless.directive.ts (skeleton)
src/app/unless.directive.ts (ctor)
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef) { }
src/app/unless.directive.ts (set)
Angular sets the appUnless property whenever the value of the condition changes.
If the condition is falsy and Angular hasn't created the view previously, the setter causes
the view container to create the embedded view from the template
If the condition is truthy and the view is currently displayed, the setter clears the container,
which disposes of the view
src/app/unless.directive.ts (excerpt)
/**
* Add the template content to the DOM unless the condition is true.
*/
@Directive({ selector: '[appUnless]'})
export class UnlessDirective {
private hasView = false;
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef) { }
src/app/app.component.ts (excerpt)
condition = false;
2. Update the template to use the directive. Here, *appUnless is on two <p> tags with opposite
condition values, one true and one false .
src/app/app.component.html (appUnless)
The asterisk is shorthand that marks appUnless as a structural directive. When the condition
is falsy, the top (A) paragraph appears and the bottom (B) paragraph disappears. When the
condition is truthy, the top (A) paragraph disappears and the bottom (B) paragraph appears.
3. To change and display the value of condition in the browser, add markup that displays the
status and a button.
src/app/app.component.html
<p>
The condition is currently
<span [ngClass]="{ 'a': !condition, 'b': condition, 'unless': true }">
{{condition}}</span>.
<button
type="button"
(click)="condition = !condition"
[ngClass] = "{ 'a': condition, 'b': !condition }" >
Toggle condition to {{condition ? 'false' : 'true'}}
</button>
</p>
To verify that the directive works, click the button to change the value of condition .
custom by adding
template
directives guard
*ngFor="let <ng-template ngFor properties
item of let-item to your
[1,2,3] as [ngForOf]=" directive
items; [1,2,3]"
de nition.
let-
trackBy: These
items="ngForOf"
myTrack;
properties
index as i"
[ngForTrackBy]="myTrack" help the
let-
Angular
i="index">
template
type
checker
nd
mistakes
in the
*ngIf="exp" <ng-template
template
[ngIf]="exp">
at
compile
time,
which can
avoid
*ngIf="exp <ng-template
[ngIf]="exp" runtime
as value"
let- errors.
value="ngIf"> These
properties
are as
follows:
Version 13.3.10-local+sha.123782bfb6.