What are structural directives?
In Angular there are 3 types of directives:
- Component – directive with the template
- Structural directives – change the DOM layout by adding and removing DOM elements.
- Attribute directives – change the look or behavior of an element, component, or another directive.
- Structural directives are responsible for the HTML layout. They shape or reshape the structure of the DOM, often by deleting or adding or manipulating elements.
- Like other directives, you can apply structural directives to the host element . They then do whatever it has to do with the host element and its descendants.
- Here I have mentioned the host element I will talk through for everyone to understand. To turn a component into something visible in the DOM, you must associate the component with an elementDOM which is called the host element , it can listen. event, update properties, can call methods on it.
For Directive . It is an element that the directive is attached to. For example, h1 is the host element
1 2 3 | <h1 my-directive> <my-comp></my-comp> |
For Component, it is the selector of the component
1 2 3 4 5 6 7 | selector: 'my-comp' template: ' <h1> some heading </h1> ..... <my-comp></my-comp> <!-- my-comp is the host element of h1 --> |
You will see there are 3 directives or use ngIf , ngFor , ngSwitch …
1 2 | <div *ngIf="dev" class="name">{{dev.name}}</div> |
1 2 3 4 | <ul> <li *ngFor="let dev of devs">{{dev.name}}</li> </ul> |
1 2 3 4 5 6 7 | <div [ngSwitch]="dev?.status"> <app-fixbug-dev *ngSwitchCase="'fixbug'" [dev]="dev"></app-fixbug-dev> <aapp-development-dev *ngSwitchCase="'development'" [dev]="dev"></app-development-dev> <app-free-dev *ngSwitchCase="'free'" [dev]="dev"></app-free-dev> <app-unknown-dev *ngSwitchDefault [dev]="dev"></app-unknown-dev> </div> |
I will not talk about how to use them here because it is not that difficult. but I will focus on explaining how they work.
We are talking about directives in this post which means we are talking about ngIf and NgIf . NgIf is referencing the directive class and ngIf is referencing the attribute name of the directive.
Directive class refers to its properties and what it does. attribute name when talking about how to apply them to an HTML template element.
As above, in my post I have listed three types of directives in Angular, one of them is the directive attribute that changes the look or behavior of an element, component, or another directive. It can be applied multiple directive attributes on a single host element.
For structural directives , they can be applied only on one host element. We can’t just use ngIf , ngFor or ngSwitch for a host element, right. Well of course Angular won’t let you do that. If you try to include * ngIf, * ngFor on the same element
1 2 3 4 5 6 7 | <ul *ngFor="let item of lists" *ngIf="heroes.length"> <button (click)="addTocart(item.hero)" class='btn btn-primary btn-sm' > +</button></li> </ul> ERROR in Template parse errors: Can't have multiple template bindings on one element. Use only one attribute prefixed with * |
The reason is:
Structural directives like ngFor can do the complex work of the host element and child element. So it will be difficult to find out which directives are applied before or after or cancel each other’s effects. When there are two directives, we cannot decide which one to take precedence.
How does directive work?
- We will find out through * ngIf
1 2 3 4 5 6 7 8 | <div *ngIf="dev"> <h2>dev name details</h2> </div> <div *ngIf="!dev"> <h2>QA name details</h2> </div> |
In fact, as we can see, it doesn’t use CSS to hide it, it adds and removes them from the DOM
When the condition is false, it removes the host element from the DOM. Separate it from the DOM event, detach from the component when it detects a change, and destroy it. Components and DOM nodes can be garbage collected and free up memory.
- Is it better to remove them from the DOM than to hide them?
The difference between hide and delete doesn’t make much sense if it’s plain text. It only really makes a difference when the component uses a lot of resources.
If when hiding a component, its behavior is still active, still attached to the DOM, continue to listen event. Angular can still track changes that may affect data binding. So even if the component is hidden, it will continue to function.
We can see the face like:
- The rendering is quick, the previous component state is kept intact and always ready to render. The component does not re-initialize this is a potentially expensive operation.
What’s inside *ngFor
?
1 2 3 4 5 6 7 8 | <div *ngFor="let dev of devs; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd"> ({{i}}) {{dev.name}} </div> <ng-template ngFor let-dev [ngForOf]="devs" let-i="index" let-odd="odd" [ngForTrackBy]="trackById"> <div [class.odd]="odd">({{i}}) {{dev.name}}</div> </ng-template> |
- Directive
ngForOf
is commonly used in the form shorthand*ngFor
. Like this example, the template that will be displayed for each loop is the content of an element that has no directive yet.
<li *ngFor="let item of items; index as i; trackBy: trackByFn">...</li>
Local variables
NgForOf
allows NgForOf
local variables to be exported:
$implicit: T
: Value of the current element in the repeating listindex: number
: index of the current iterationcount: number
: Number of items in the listfirst: boolean
: True: If the first item in the listlast:boolean
: True: If the last item in the listeven: true
: If the element in the index is evenodd: true
: If the element is at an odd index
We can access the exported *ngFor
variables of two types:
1 2 3 4 5 6 7 8 9 | c1 <li *ngFor="let user of users; index as i; first as isFirst"> {{i}}/{{users.length}}. {{user}} <span *ngIf="isFirst">default</span> </li> c2 <div *ngFor="let dev of devs; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd"> ({{i}}) {{dev.name}} </div> |
Change propagation
- When the content of the loop changes
ngForOf
makes changes corresponding to the DOM:
- When an item is added, a new instance of the template is added to the DOM
- When an item is deleted, its instance template is removed from the DOM.
- When items are rearranged, their respective templates are rearranged in the DOM.
In *ngFor
have config help improve its performance tracking algorithm is customizable default, it provides us chho trackBy
with ngForOf
. trackby
provided with 2 parameters input index
and item
. Angular will tracking
value varies as a function returns.
*ngIf
?
- This is a structural directive that displays the view (template) portion according to a condition
- This is the most commonly used structural directive, and the template else defaults to blank
- Its shorthand form
*ngIf="condition"
, is usually used to provide as an attribute of the anchor element to the*ngIf="condition"
template. Angular also extends this to a more explicit syntax where the anchored element is not already in the template
shorthand syntax:
1 2 | <div *ngIf="condition">Content to render when condition is true.</div> |
Simple form with expanded syntax:
1 2 | <ng-template [ngIf]="condition"><div>Content to render when condition istrue.</div></ng-template> |
Form with an “else” block:
1 2 3 | <div *ngIf="condition; else elseBlock">Content to render when condition is true.</div> <ng-template #elseBlock>Content to render when condition is false.</ng-template> |
Inside NgSwitch directives
Here is the syntax
1 2 3 4 5 6 | <container-element [ngSwitch]="switch_expression"> <some-element *ngSwitchCase="match_expression_1">...</some-element> ... <some-element *ngSwitchDefault>...</some-element> </container-element> |
- The value of the expression assigned to [NgSwitch] if present is displayed
- [NgSwitch] itself is not a structural directive. It’s just one attributes directive that controls the behavior of two other conversion directives. That’s why we write it as [NgSwitch], not * ngSwitch
- NgSwitchCase and NgSwitchDefault are structural directives. You will attach them to the element so it looks like that (
<some-element *ngSwitchDefault>...</some-element>
) AnNgSwitchCase
shows host element when its value matches the switch value.NgSwitchDefault
will show up when its sibling cases don’t have a match. You can see it’s almost like any other language switch.
1 2 3 4 5 6 | Trên đây là nhưng gì tôi đã tìm hiểu được về structural directive nhưng cái cần nắm : 1. Cơ chế hoạt động của nó là xóa khỏi DOM 2. cú pháp của directive 3. element mà bạn áp dụng directive thì được gọi là host element. |
Reference source :