Как передать данные из дочернего компонента в родительский?

В Angular есть несколько способов передачи данных из дочернего компонента в родительский. Рассмотрим несколько вариантов.

  1. Использование свойств и событий:

    Дочерний компонент может передать данные родительскому компоненту через свойства и события. Вот пример:

    В дочернем компоненте (child.component.ts):

    import { Component, Output, EventEmitter } from '@angular/core'
    
    @Component({
    	selector: 'app-child',
    	template: ` <button (click)="sendMessage()">Отправить сообщение</button> `
    })
    export class ChildComponent {
    	@Output() messageEvent = new EventEmitter<string>()
    
    	sendMessage() {
    		const message = 'Привет, родительский компонент!'
    		this.messageEvent.emit(message)
    	}
    }
    

    В родительском компоненте (parent.component.html):

    <app-child (messageEvent)="receiveMessage($event)"></app-child>
    <p>{{ receivedMessage }}</p>
    
    import { Component } from '@angular/core'
    
    @Component({
    	selector: 'app-parent',
    	templateUrl: './parent.component.html'
    })
    export class ParentComponent {
    	receivedMessage: string
    
    	receiveMessage(message: string) {
    		this.receivedMessage = message
    	}
    }
    

    В этом примере мы используем событие messageEvent, которое определено в дочернем компоненте через декоратор @Output(). При клике на кнопку в дочернем компоненте, мы вызываем метод sendMessage(), который отправляет сообщение через событие messageEvent.emit(message). В родительском компоненте мы прослушиваем событие (messageEvent) и вызываем метод receiveMessage(), который принимает переданное сообщение и сохраняет его в свойстве receivedMessage. Затем мы отображаем receivedMessage в шаблоне родительского компонента.

  2. Использование сервиса:

    Другой способ передачи данных из дочернего компонента в родительский - использование общего сервиса. Вот пример:

    Создайте сервис (data.service.ts):

    import { Injectable } from '@angular/core'
    import { Subject } from 'rxjs'
    
    @Injectable()
    export class DataService {
    	private messageSource = new Subject<string>()
    	message$ = this.messageSource.asObservable()
    
    	sendMessage(message: string) {
    		this.messageSource.next(message)
    	}
    }
    

    В дочернем компоненте (child.component.ts):

    import { Component } from '@angular/core'
    import { DataService } from '../data.service'
    
    @Component({
    	selector: 'app-child',
    	template: ` <button (click)="sendMessage()">Отправить сообщение</button> `
    })
    export class ChildComponent {
    	constructor(private dataService: DataService) {}
    
    	sendMessage() {
    		const message = 'Привет, родительский компонент!'
    		this.dataService.sendMessage(message)
    	}
    }
    

В родительском компоненте (parent.component.html):

<p>{{ receivedMessage }}</p>

В родительском компоненте (parent.component.ts):

import { Component, OnDestroy } from '@angular/core'
import { DataService } from '../data.service'
import { Subscription } from 'rxjs'

@Component({
	selector: 'app-parent',
	templateUrl: './parent.component.html'
})
export class ParentComponent implements OnDestroy {
	receivedMessage: string
	subscription: Subscription

	constructor(private dataService: DataService) {
		this.subscription = this.dataService.message$.subscribe((message) => {
			this.receivedMessage = message
		})
	}

	ngOnDestroy() {
		this.subscription.unsubscribe()
	}
}

В этом примере мы создали сервис DataService, который содержит Subject - messageSource. Дочерний компонент использует этот сервис и вызывает метод sendMessage() для передачи сообщения. Родительский компонент подписывается на message$, который является Observable, в методе ngOnInit() и сохраняет полученное сообщение в свойстве receivedMessage. Мы отображаем receivedMessage в шаблоне родительского компонента. Обратите внимание, что мы также отписываемся от subscription в методе ngOnDestroy(), чтобы избежать утечки памяти.

В обоих примерах мы рассмотрели способы передачи данных из дочернего компонента в родительский в Angular. Выбор метода зависит от конкретной ситуации и требований вашего приложения.