Angular is built to pass data to children components via properties (input) and send back to parents with events (output).
In your scenario I can't see nay reason to not pass data to the parent in an @Output property:
@Output() test = new EventEmitter<any>();
private sendDataToParent(data:any): void {
this.test.emit(data);
}
<app-child (test)="parentMethod($event)></app-child>
If you need to expand your knowledge about this topic you should read this documentation:
https://angular.io/guide/component-interaction
Anyway, sometimes you need the same data across multiple components, multiple parents or children, and you can use Observables to manage this, but you should create a service to be injected in all that components.
@Injectable()
export class MyDataService {
private dataSubject$: BehaviorSubject<MyData> = new BehaviorSubject<MyData>(null);
getData$(): Observable<MyData> {
return this.dataSubject$;
}
changeData(data: MyData) {
this.dataSubject$.next(data);
}
}
And your components can subscribe to that service:
export class MyComponent implements OnInit {
public data$: Observable<MyData>;
constructor(private dataService: MyDataService) {
this.data$ = this.dataService.getData$();
}
ngOnInit() {}
changeData(data: MyData) {
this.dataService.changeData(data);
}
}
You can use data$ in your html with async pipe, or if you prefer you can subscribe manually in code, but don't forget to unsubscribe inside ngOnDestroy, this could be a way to do it:
export class MyComponent implements OnInit, OnDestroy {
private destroy$ = new BehaviorSubject<boolean>(false);
constructor(private dataService: MyDataService) {}
ngOnInit() {
this.dataService.getData$()
.pipe(takeUntil(this.detroy$))
.subscribe(data => {
// do x
});
}
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.unsubscribe();
}
changeData(data: MyData) {
this.dataService.changeData(data);
}
}