Angular 19: Немаркированные шаблонные литералы в выражениях
 
        В версии Angular 19.2.0 появилась возможность использовать немаркированные шаблонные литералы в выражениях. Это позволяет интерполировать переменные, используя обратные кавычки, непосредственно внутри Angular-выражений в шаблонах. Главная цель нововведения – упростить конкатенацию строк в шаблонах компонентов.
Поддерживаются следующие сценарии:
- Одинарная интерполяция
- Множественная интерполяция
- Интерполяция с пайпом
Функционал доступен начиная с версии 19.2.0-next и может быть протестирован в демо-примере на Stackblitz.
ng update @angular/cli --next
ng update @angular/core --nextОдинарная интерполяция
@Component({
 selector: 'app-root',
 templateUrl: `./main.component.html`,
 changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {
 description = `${VERSION.full} - Untagged Template Literals`;
}// main.component.html
<h1>Version {{ description }}</h1>До использования немаркированного шаблонного литерала статический текст «Version» располагается перед выражением.
// main.component.html
<h1>{{ `Version ${description}` }}</h1>После применения функционала немаркированных шаблонных литералов статический текст «Version» и выражение description объединяются в одну строку. Элемент h1 отображает "Version 19.2.0-next.0 - Unlabeled Template Literals".
Множественная интерполяция
@Component({
 selector: 'app-root',
 templateUrl: `./main.component.html`,
 changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {
 description = `${VERSION.full} - Untagged Template Literals`;
 userName = signal('N/A');
 userType = signal<"user" | "admin" | "intruder">('user');
 componentType = computed(() => configs[this.userType()]);
 inputs = computed(() => ({
     permissions: this.componentType().permissions,
     name: this.userName(),
     type: this.userType(),
 }));
}// main.component.html
@let ct = componentType();
<ng-container [ngComponentOutlet]="ct.type"
 [ngComponentOutletInputs]="inputs()"
 #instance="ngComponentOutlet"
/>
@let permissions = componentInstance?.permissions() ?? [];
@let strPermission = permissions.join(', ');
@let numPermissions = permissions.length;
@let permissionUnit = numPermissions > 1 ? 'permissions' : 'permission';
@let delimiter = numPermissions >= 1 ? ', ' : '';
Multiple Interpolations: {{ numPermissions }} {{ permissionUnit }}{{ delimiter}}{{strPermission} }}Переменная componentInstance содержит динамически отрисованный компонент. Переменная permissions хранит массив разрешений отрисованного компонента. Переменная strPermission объединяет массив permissions в строку. Переменная permissionUnit принимает значение «permissions», если у пользователя несколько разрешений, и «permission» – если разрешение одно или отсутствует. Запятая добавляется перед строкой разрешений, если у пользователя более одного разрешения.
Перед использованием немаркированного шаблонного литерала статический текст "Multiple Interpolations" располагается перед выражениями. Все выражения – numPermissions, permissionUnit, delimiter и strPermission – интерполируются по отдельности.
// main.component.html
@let permissions = componentInstance?.permissions() ?? [];
@let strPermission = permissions.join(', ');
@let numPermissions = permissions.length;
@let permissionUnit = numPermissions > 1 ? 'permissions' : 'permission';
@let delimiter = numPermissions >= 1 ? ', ' : '';
{{ `Multiple Interpolations: ${numPermissions} ${permissionUnit}${delimiter}${strPermission}` }}После применения немаркированных шаблонных литералов эти переменные объединяются и интерполируются внутри фигурных скобок Angular-выражения.
- Если тип пользователя – Admin, строка шаблона принимает значение «Multiple Interpolations: 4 permissions: create (создание), edit (редактирование), view (просмотр), delete (удаление)».
- Если тип пользователя – User, строка шаблона принимает значение «Multiple Interpolations: 1 permission: view».
- Если тип пользователя – Intruder, строка шаблона принимает значение «Multiple Interpolations: 0 permissions».
Интерполяция с пайпом
@Component({
 selector: 'app-admin',
 templateUrl: `app-user.component.html`,
 imports: [TitleCasePipe],
 changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AdminComponent implements Permission {
 permissions = input.required<string[]>();
 name = input('N/A');
 type = input.required<string>();
}Компонент AdminComponent импортирует пайп TitleCasePipe для преобразования разрешений и типа пользователя к верхнему регистру.
Перед немаркированным шаблонным литералом значение сигнала type передается в пайп titleCase. Затем следует статический текст "Component" с предшествующим пробелом.
После применения немаркированных шаблонных литералов преобразованное значение сигнала объединяется со статическим текстом "Component", формируя новую строку внутри Angular-выражения.
- Если тип пользователя – Admin, строка шаблона принимает значение «Admin Component».
- Если тип пользователя – User, строка шаблона принимает значение «User Component».
- Если тип пользователя – Intruder, строка шаблона принимает значение «Intruder Component».
Функция немаркированных шаблонных литералов предоставляет удобный способ объединения строк и их вычисления внутри Angular-выражений. В зависимости от стиля кода и предпочтений команды разработчики могут использовать как немаркированные шаблонные литералы, так и ES6 шаблонные строки для конкатенации и интерполяции строк в шаблонах.