Angular 22 вышел 3 июня 2026 года со стабильными Signal Forms, модулем доступности Angular Aria, декларативной загрузкой данных через Signals, OnPush по умолчанию и Fetch API как основным HTTP-клиентом. Полный разбор всех нововведений с примерами кода, стратегиями миграции и практическими рекомендациями.
Angular 22 выпущен 3 июня 2026 года. Это самый значительный релиз Angular со времён v17 (standalone components) — фреймворк окончательно переходит на signal-first архитектуру. Signal Forms становятся стабильными, OnPush включается по умолчанию, HTTP-клиент использует Fetch API, а новый модуль Angular Aria предоставляет встроенную доступность. 10 июня вышло обновление 22.0.1 с исправлениями безопасности и санитизацией SVG-атрибутов.
Перешли из developer preview в стабильную версию — реактивные формы на Angular Signals, готовые к production.
Встроенные примитивы доступности (WCAG) — ARIA-директивы, клавиатурная навигация, экранные читалки.
Декларативная загрузка данных через Signals с автоматическими состояниями и цепочками зависимостей.
Компоненты без явного changeDetection теперь используют OnPush. Автоматическая миграция через schematics.
HttpClient использует FetchBackend. XHR через withXhr(). withFetch() объявлен устаревшим.
Прекращена поддержка TypeScript 5.x и Node.js 20. Требуется TS 6.0+ и Node.js v22+.
Новый декоратор для сервисов с улучшенной типобезопасностью фабричных функций.
ComponentFactoryResolver и ComponentFactory удалены. Передавайте классы компонентов напрямую.
Разберём каждое нововведение подробно — что оно делает, зачем нужно и как использовать уже сегодня.
Самое значительное нововведение Angular 22 — перевод Signal Forms из developer preview в стабильный статус. После месяцев доработок — ленивая инициализация полей, поддержка generic union-типов, debounced async-валидация, сигналы ошибок парсинга, настраиваемое поведение отправки и сброс кастомных контролов — Signal Forms готовы к production.
Signal Forms заменяют template-driven и reactive forms единым сигнал-ориентированным API. Вместо
FormControl, FormGroup и FormArray вы получаете реактивные
примитивы полей на базе Angular Signals — автоматическое, гранулярное обнаружение изменений без zone.js.
export class LoginComponent {
form = new FormGroup({
email: new FormControl('', [Validators.required, Validators.email]),
password: new FormControl('', [Validators.required, Validators.minLength(8)]),
});
get email() { return this.form.get('email'); }
onSubmit() {
if (this.form.valid) {
this.authService.login(this.form.value);
}
}
}
import { signalForm, formField } from '@angular/forms';
export class LoginComponent {
form = signalForm({
email: formField('', { validators: [required, email] }),
password: formField('', { validators: [required, minLength(8)] }),
});
// Состояние формы реактивно через Signals
emailError = computed(() => {
const field = this.form.controls.email;
if (field.touched() && field.invalid()) {
return field.getError('email') ?? 'Неверный email';
}
return null;
});
onSubmit() {
if (this.form.valid()) {
this.authService.login(this.form.value());
}
}
}
Ключевые отличия: Signal Forms отслеживают valid, touched, dirty и errors через Signals, а не через
observable-потоки. Нет .get() со строковыми путями — поля доступны как типизированные
свойства. Схема определения компактна и компонуема, поддерживает вложенные группы, динамические
массивы и union-типы на уровне схемы.
Angular 22 поставляет Angular Aria как стабильный модуль — комплексный набор примитивов доступности, делающий соответствие WCAG встроенной возможностью фреймворка, а не сторонней библиотекой.
Angular Aria включает директивы для:
import { AriaModule } from '@angular/aria';
@Component({
selector: 'app-modal',
standalone: true,
imports: [AriaModule],
template: `
<div role="dialog" ariaModal ariaLabelledBy="modal-title">
<h2 id="modal-title">Подтверждение</h2>
<p>Вы уверены, что хотите удалить этот элемент?</p>
<div class="actions" ariaKeyboardNav>
<button (click)="confirm()">Удалить</button>
<button (click)="cancel()">Отмена</button>
</div>
</div>
`
})
export class ConfirmModalComponent {}
httpResource и rxResource — это смена парадигмы в том, как Angular-приложения загружают и управляют данными. Вместо ручного управления жизненным циклом запросов с подписками, флагами загрузки и состояниями ошибок вы объявляете зависимость данных как Signal — Angular делает всё остальное.
import { httpResource } from '@angular/common/http';
@Component({
selector: 'app-user-profile',
template: `
@if (user.isLoading()) {
<p>Загрузка...</p>
} @else if (user.error()) {
<p>Ошибка: {{ user.error() }}</p>
} @else {
<h2>{{ user.value().name }}</h2>
<p>{{ user.value().email }}</p>
}
`
})
export class UserProfileComponent {
userId = input<number>();
// Декларативно — httpResource реагирует на изменение userId
user = httpResource<User>(() => `/api/users/${this.userId()}`, {
defaultValue: { name: '', email: '' }
});
}
httpResource возвращает объект с тремя реактивными свойствами: value (Signal с данными),
isLoading (Signal-флаг загрузки) и error (Signal с ошибкой). При изменении URL
ресурс автоматически перезапрашивает данные.
// Данные команды загружаются после выбора ID
team = httpResource<Team>(() => `/api/teams/${this.selectedTeamId()}`);
// Участники загружаются, когда есть данные о команде
teamMembers = this.team.chain(
(team) => `/api/teams/${team.id}/members`,
{ defaultValue: [] as Member[] }
);
// Задачи участников загружаются на основе участников
teamTasks = this.teamMembers.chain(
(members) => `/api/tasks?assigneeIds=${members.map(m => m.id).join(',')}`,
{ defaultValue: [] as Task[] }
);
Каждый вызов chain() создаёт зависимый ресурс, который автоматически перезапрашивается
при изменении родительского. Race conditions обрабатываются — если родительский ресурс перезагружается
до завершения дочернего, устаревший запрос отменяется.
Начиная с Angular 22, компоненты без явного changeDetection по умолчанию
используют ChangeDetectionStrategy.OnPush. Это breaking change, который
приводит Angular в соответствие с современными реактивными паттернами.
Для сохранения старого поведения укажите явно:
@Component({
selector: 'app-legacy',
changeDetection: ChangeDetectionStrategy.Eager, // было Default
template: `...`
})
export class LegacyComponent {}
Схема ng update автоматически находит компоненты, полагавшиеся на старое поведение,
и добавляет ChangeDetectionStrategy.Eager там, где это необходимо. Если вы уже
используете Signals, это изменение будет прозрачным — ваши компоненты уже ведут себя как OnPush.
Angular 22 переключает HTTP-клиент с XMLHttpRequest на современный Fetch API.
HttpClient теперь использует FetchBackend по умолчанию.
// По умолчанию в v22 — Fetch используется автоматически
provideHttpClient()
// Для XHR (прогресс загрузки файлов)
provideHttpClient(withXhr())
withFetch() объявлен устаревшим — он больше не нужен, так как Fetch стал поведением
по умолчанию. Схема миграции добавляет withXhr() автоматически для проектов,
использовавших provideHttpClient без аргументов.
Angular 22 прекращает поддержку TypeScript 5.x и Node.js 20. Требуется обновление до:
Схема ng update добавляет "strictTemplates": true в tsconfig и
отключает диагностики nullishCoalescingNotNullable и optionalChainNotNullable,
которые TS 6.0 может активировать на существующих шаблонах.
Новый декоратор для сервисов с улучшенной типобезопасностью фабричных функций — более явная
альтернатива @Injectable({ providedIn: 'root' }).
Новая функция для асинхронного внедрения зависимостей — полезна для lazy-загрузки сервисов и динамических провайдеров.
paramsInheritanceStrategy теперь по умолчанию 'always' — параметры
маршрутов наследуются от всех родительских маршрутов. provideRoutes() удалён.
Добавлены опции для поведения несоответствующих входных данных компонентов.
Angular 22 включает инкрементальную гидратацию по умолчанию для SSR-приложений — компоненты гидратируются по мере появления в области видимости, сокращая Time to Interactive.
ComponentFactoryResolver и ComponentFactory — передавайте классы напрямую в ViewContainerRef.createComponent()createNgModuleRef — используйте createNgModuleChangeDetectorRef.checkNoChanges — используйте fixture.detectChanges()provideRoutes() — используйте provideRouter()Пошаговый чеклист для обновления:
npm install typescript@~6.0ng update @angular/core@22 @angular/cli@22 — автоматически:
ChangeDetectionStrategy.EagerprovideRoutes() → provideRouter()provideHttpClientstrictTemplates и отключит nullable-диагностикиwithXhr() для upload-прогрессаmin и max больше не принимают строкиwithFetch() из конфигурации провайдеровChangeDetectionStrategy.Eager или мигрируйте на SignalsДа — для большинства проектов. Signal-first направление — это будущее Angular, и v22 предоставляет стабильную основу для этого перехода:
Я занимаюсь Angular-разработкой с Angular 2 (2016) и мигрировал проекты с v2 по v21. Обновление до v22 — одно из самых плавных. Схемы миграции comprehensive, а signal-first архитектура реально улучшает производительность и опыт разработки. Если нужна помощь с миграцией или архитектурой — свяжитесь со мной.
Я разрабатываю production-приложения на Angular и помогаю с миграцией на v22, архитектурой и full-stack разработкой. Бесплатная консультация.