Структурные директивы изменяют структуру DOM с помощью добавления или удаления html-элементов. Рассмотрим три структурных директивы: ngIf, ngSwitch и ngFor.
Директива ngIf позволяет удалить или, наоборот, добавить элемент при определенном условии. Например, определим следующий компонент:
import { Component} from "@angular/core"; import {NgIf} from "@angular/common"; @Component({ selector: "my-app", standalone: true, imports: [NgIf], template: `<p *ngIf="condition"> Привет мир </p> <p *ngIf="!condition"> Пока мир </p> <button (click)="toggle()">Toggle</button>` }) export class AppComponent { condition: boolean=true; toggle(){ this.condition=!this.condition; } }
Для использования директивы надо импортировать соответствующий класс NgIf из пакета "angular/common"
В шаблоне компонента зависимости от значения свойства condition
будет отображаться либо первый, либо второй параграф.
Мы можем задавать альтернативные выражения с помощью директивы ng-template. Так, предыдущий пример будет аналогичен следующему:
import { Component} from "@angular/core"; import {NgIf} from "@angular/common"; @Component({ selector: "my-app", standalone: true, imports: [NgIf], template: `<p *ngIf="condition;else unset"> Привет мир </p> <ng-template #unset> <p>Пока мир</p> </ng-template> <button (click)="toggle()">Toggle</button>` }) export class AppComponent { condition = true; toggle(){ this.condition=!this.condition; } }
Выражение *ngIf="condition;else unset"
указывает, что если condition равно false, то срабатывает блок <ng-template #unset>
.
Либо можно определить более изощренную логику. Так, изменим шаблон компонента следующим образом:
template: ` <div *ngIf="condition; then thenBlock else elseBlock"></div> <ng-template #thenBlock>Then template</ng-template> <ng-template #elseBlock>Else template</ng-template> <button (click)="toggle()">Toggle</button>`
В данном случае, если condition равно true, то отображается блок thenBlock, иначе отображается блок elseBlock.
Директива ngFor позволяет перебрать в шаблоне элементы массива. Например:
import { Component} from "@angular/core"; import {NgFor} from "@angular/common"; @Component({ selector: "my-app", standalone: true, imports: [NgFor], template: `<ul> <li *ngFor="let item of items">{{item}}</li> </ul>` }) export class AppComponent { items =["Tom", "Bob", "Sam", "Bill"]; }
В качестве значения директива принимает значение перебора аля-foreach: let item of items
. Каждый перебираемый элемент помещается в
переменную item
, которую мы можем вывести на страницу.
При переборе элементов нам доступен текущий индекс элемента через переменную index, которую мы также можем использовать. Например:
<div> <p *ngFor="let item of items; let i = index">{{i+1}}.{{item}}</p> </div>
Надо учитывать, что индексация идет с нуля, поэтому, чтобы в данном случае отсчет шел с единицы, к переменной i прибавляется единица.
Можно заметить, что при использовании директив ngFor и ngIf перед ними ставится символ звездочка. По факту это не более чем синтаксический сахар, который упрощает применение
директивы. Так, определение ngIf
:
<p *ngIf="condition"> Привет мир </p> <p *ngIf="!condition"> Пока мир </p>
по факту будет представлять следующий код:
<ng-template [ngIf]="condition"> <p> Привет мир </p> </ng-template> <ng-template [ngIf]="!condition"> <p> Пока мир </p> </ng-template>
В итоге параграф и его текст перемещаются внутрь элемента <ng-template>
.
Сама директива помещается в тег <ng-template>
, в котором применяется привязка свойства. Булевое значение привязанного свойство указывает, надо ли
отображать соответствующий контент.
В итоге мы можем выбирать либо первый способ со звездочкой, который более компактный, либо второй способ с элементами ng-template.
То же самое касается и директивы ngFor:
<ul> <li *ngFor="let item of items">{{item}}</li> </ul>
Этот код будет эквивалентен следующему:
<ul> <ng-template ngFor let-item [ngForOf]="items"> <li>{{item}}</li> </ng-template> </ul>
С помощью директивы ngSwitch можно встроить в шаблон конструкцию switch..case и в зависимости от ее результата выполнения выводить тот или иной блок. Например:
import { Component} from "@angular/core"; import {NgSwitch, NgSwitchCase, NgSwitchDefault} from "@angular/common"; @Component({ selector: "my-app", standalone: true, imports: [NgSwitch, NgSwitchCase, NgSwitchDefault], template: `<div [ngSwitch]="count"> <ng-template ngSwitchCase="1">{{count * 10}}</ng-template> <ng-template ngSwitchCase="2">{{count * 100}}</ng-template> <ng-template ngSwitchDefault>{{count * 1000}}</ng-template> </div>` }) export class AppComponent { count = 5; }
Директива ngSwitch в качестве значения принимает некоторое выражение. В данном случае это свойство count. В элемент ng-template
помещается директива ngSwitchCase
, которая сравнивает значение выражения из ngSwitch с другим выражением. Если оба выражения равны, то
используется данный элемент template. Иначе выполнение переходит к следующим инструкциям ngSwitchCase. Если же ни одна из инструкций ngSwitchCase не была выполнена,
то вызывается инструкция ngSwitchDefault
.