Гид по технологиям

Декоратор Output в Angular: передача событий и данных от дочернего к родительскому компоненту

6 min read Angular Обновлено 03 Jan 2026
Output в Angular — передача событий и данных
Output в Angular — передача событий и данных

Декоратор Output позволяет дочернему компоненту отправлять события и данные в родительский компонент через EventEmitter. Это простой и типобезопасный способ коммуникации «снизу вверх» в Angular — пригодится для уведомлений, передачи списков или любых небольших пакетов данных. В статье — пошаговый пример, проверки, альтернативы и рекомендации по отладке и безопасности.

Введение

Два монитора рядом, один крупный, другой маленький, на каждом открыто окно редактора с кодом

В Angular веб-страница обычно состоит из множества переиспользуемых компонентов. Каждый компонент имеет свою TypeScript-логику, шаблон HTML и CSS-стили. Часто нужно, чтобы дочерний компонент уведомил родителя о каком-то действии или передал данные — для этого используется декоратор Output и класс EventEmitter.

Короткие определения:

  • Output — декоратор для публичного события компонента.
  • EventEmitter — класс, через который компонент испускает (emit) события типа T.

Важно: Output передаёт данные только в направлении «дочерний → родитель» через привязку события в шаблоне родителя.

Когда использовать Output

  • Нужны локальные уведомления (клик, выбор, подтверждение) от дочернего к родительскому компоненту.
  • Передаётся небольшая порция данных (например, id, массив имён, объект формы).
  • Не требуется глобальное состояние или кэширование между удалёнными компонентами.

Важно: если нужно делиться состоянием между несвязанными компонентами (без иерархии), лучше использовать сервисы, RxJS или хранилище (NgRx/Vikx).

Как добавить декоратор Output в дочерний компонент

Ниже — шаг за шагом с примером. Код-блоки сохранены без изменений.

  1. Создайте новое приложение Angular с родительским компонентом (по умолчанию — app) и дочерним компонентом.

  2. Замените содержимое app.component.html:

This is the parent component

  1. Стили для родительского компонента (app.component.css):
.parent-component {  
  font-family: Arial, Helvetica, sans-serif;  
  background-color: lightcoral;  
  padding: 20px  
}
  1. Создайте дочерний компонент командой:
ng g c data-component
  1. Замените содержимое data-component.component.html, добавив кнопку и привязав её к функции onButtonClick():

This is the child component

  1. Стили для дочернего компонента (data-component.component.css):
.child-component {  
  font-family: Arial, Helvetica, sans-serif;  
  background-color: lightblue;  
  margin: 20px;  
  padding: 20px  
}
  1. В файле data-component.component.ts добавьте заготовку функции:
onButtonClick() {  
}
  1. Импортируйте Output и EventEmitter:
import { Component, Output, EventEmitter, OnInit } from '@angular/core';
  1. Объявите свойство Output в классе дочернего компонента:
export class DataComponentComponent implements OnInit {  
  @Output() buttonWasClicked = new EventEmitter();  
  // ...  
}
  1. Вызовите emit() внутри onButtonClick(), чтобы уведомить родителя:
onButtonClick() {  
    this.buttonWasClicked.emit();  
}

Как слушать события дочернего компонента из родителя

Чтобы обработать событие, нужно подписаться на него в шаблоне родителя:

  1. Используйте дочерний компонент в app.component.html и подпишитеся на событие buttonWasClicked:
  1. Добавьте обработчик в app.component.ts:
message: string = ""  
  
buttonInChildComponentWasClicked() {  
    this.message = 'The button in the child component was clicked';  
}
  1. Отобразите сообщение в шаблоне:

{{message}}

  1. Запустите приложение командой ng serve и откройте http://localhost:4200. Родитель и ребёнок будут с разными фонами для наглядности.

Angular приложение с родительским и дочерним компонентами в Firefox

  1. Нажмите кнопку Click me — событие отправится вверх, и родитель отобразит сообщение.

Angular приложение с отображением результата в Firefox

Как передать данные от дочернего компонента к родительскому

Output может передавать не только события без нагрузки, но и данные любого типа T.

  1. В data-component.component.ts объявите массив строк:
listOfPeople: string[] = ['Joey', 'John', 'James'];
  1. Измените тип EventEmitter с void на string[]:
@Output() buttonWasClicked = new EventEmitter();
  1. Передавайте данные через emit():
onButtonClick() {  
    this.buttonWasClicked.emit(this.listOfPeople);  
}
  1. В шаблоне родителя получайте $event:
  1. Обновите обработчик в app.component.ts:
buttonInChildComponentWasClicked(dataFromChild: string[]) {  
    this.message = 'The button in the child component was clicked';  
}
  1. Сохраните пришедшие данные в свойстве data:
message: string = ""  
data: string[] = []  
  
buttonInChildComponentWasClicked(dataFromChild: string[]) {  
    this.message = 'The button in the child component was clicked';  
    this.data = dataFromChild;  
}
  1. Отобразите данные в шаблоне:

{{data.join(', ')}}

  1. Запустите приложение и проверьте: по клику родитель получит массив имён и отобразит их.

Angular приложение с родителем и дочерним компонентом в Firefox

Angular приложение, отображающее полученные данные в Firefox

Частые ошибки и отладка (Когда это не работает)

  • Неправильно импортирован Output/EventEmitter или опечатка в импорте. Проверьте: import { Output, EventEmitter } from ‘@angular/core’.
  • Отсутствует привязка события в шаблоне родителя: убедитесь, что вы используете (buttonWasClicked) в теге дочернего компонента.
  • Неправильный тип Generic в EventEmitter — TypeScript не бросит runtime-ошибку, но данные могут быть не того вида. Совпадение типов помогает избежать багов.
  • Ошибка: дочерний компонент не включён в шаблон родителя (не вставлен тег) или модуль не объявляет компонент.
  • Если компонент создаётся динамически через ViewContainerRef, подписка может требовать ручной привязки.

Отладочные шаги:

  • Добавьте console.log в onButtonClick() и в обработчике родителя.
  • Временно используйте EventEmitter для проверки структуры данных.
  • Проверьте, что селектор у дочернего компонента совпадает с используемым тегом.

Альтернативы и когда их использовать

  1. Сервисы с RxJS (Subject / BehaviorSubject)

    • Подходящ, когда нужно обмениваться данными между несвязанными компонентами или сохранить состояние.
    • Преимущества: централизованное состояние, историчность (BehaviorSubject держит последнее значение).
    • Недостаток: выше связность через сервис, сложнее проследить поток событий при отладке.
  2. Input + двухсторонняя привязка (по шаблону)

    • Используйте Input, если данные должны течь сверху вниз; комбинируйте с Output для двусторонней связи.
  3. Управляемое хранилище (NgRx, Akita и др.)

    • Подходит для крупных приложений с множеством источников правки и сложной бизнес-логикой.
  4. Event Bus (глобальные события)

    • Рекомендуется избегать в большинстве случаев: трудно отследить зависимости и отладить.

Шаблон действий (мини-методология)

  1. Определите направление данных: дочерний → родитель? используйте Output.
  2. Выберите тип данных T и укажите его в EventEmitter.
  3. На дочернем компоненте вызывайте emit(data).
  4. На родительском компоненте подпишитесь в шаблоне через (event)=”handler($event)”.
  5. Протестируйте: unit + интеграционные тесты (см. раздел тестов).

Критерии приёмки

  • Нажатие на кнопку в дочернем компоненте вызывает метод onButtonClick().
  • Вызов onButtonClick() испускает событие через buttonWasClicked.emit() с ожидаемым payload.
  • Родитель получает событие и сохраняет/отображает полученные данные.
  • Нет ошибок в консоли браузера при исполнении сценария.

Контрольный список для разработчика

  • Импортированы Output и EventEmitter из @angular/core.
  • EventEmitter имеет корректный тип ().
  • Вызов emit() выполняется в нужной точке логики.
  • Родитель использует (eventName) в шаблоне.
  • Обработчик родителя принимает аргумент и безопасно его использует.
  • Добавлены unit-тесты на emit и обработку события.

Тестовые случаи / Критерии приёмки (минимальные)

  • При клике вызывается onButtonClick() — проверка spy/spyOn.
  • После emit родительский метод получает корректный параметр ($event).
  • Если передаётся массив, он не мутируется при приёме (проверить неизменность, если нужно).

Шаблоны кода — быстрый cheat sheet

Простой EventEmitter (без данных):

@Output() closed = new EventEmitter();

close() {
  this.closed.emit();
}

EventEmitter с данными:

@Output() selected = new EventEmitter();

select(id: number) {
  this.selected.emit(id);
}

Подписка в родителе:

Безопасность и приватность данных

  • Не отправляйте через Output чувствительные данные (пароли, токены). События проходят через приложение и могут быть прочитаны в консоли при неправильной обработке.
  • Для сложных объектов думайте об их клонировании при отправке, чтобы избежать непреднамеренных мутаций (Object.assign / spread / JSON clone).

Производительность и масштабируемость

  • Частые события с большими объектами приводят к копированию и нагрузке. Отправляйте минимальный объём данных (id вместо полного объекта).
  • Для высокочастотных обновлений используйте сервисы и потоковые решения (throttle/debounce, RxJS).

Примеры, когда Output не подходит (контрпримеры)

  • Нужен общий доступ к состоянию между несвязанными компонентами — лучше сервис.
  • Понадобится сохранять историю изменений — используйте BehaviorSubject/Store.
  • Компоненты находятся в разных фреймворках/песочницах — Output не пересечёт границ iframe.

Рекомендации по стилю и архитектуре

  • Всегда типизируйте EventEmitter.
  • Не используйте Output для изменения глобального состояния напрямую — делегируйте обновления сервисам.
  • Документируйте контракт события: что содержит payload и какие гарантии формата.

Маленькая памятка (1‑строчная глоссарий)

  • Output — «входящие» события дочернего компонента, которые родитель может слушать; EventEmitter — механизм их отправки.

Короткое руководство к внедрению в проект (SOP)

  1. Создать компонент или определить существующий.
  2. Добавить @Output() имяСобытия = new EventEmitter<Тип>();
  3. Вызывать this.имяСобытия.emit(данные) при нужном действии.
  4. В родительском шаблоне повесить (имяСобытия)=”обработчик($event)”.
  5. Протестировать и покрыть unit-тестами.

Итог

Декоратор Output — это простой, типобезопасный способ организовать связь «дочерний → родитель» в Angular. Для передачи состояния между несвязанными компонентами используйте сервисы или паттерны управления состоянием. Соблюдайте правила типизации и не передавайте через события чувствительные данные.

Короткие выводы:

  • Output + EventEmitter — лучший выбор для локальных уведомлений.
  • Типизация EventEmitter повышает надёжность.
  • Для глобального состояния — сервисы и RxJS.

Спасибо за чтение — применяйте Output осознанно и тестируйте интеграцию компонентов.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство