As it looks like you are looking to redirect to those components, what you can do is have an event emitter on component one, that on click will emit the data to the parent(of all 3). Then in the parent you would catch the emit, and assign that to data that you pass into the other components.
Component1
import { Component, EventEmitter, Output } from '@angular/core';
import { Router } from '@angular/router';
@Component(...)
export class Component1 {
@Output() redirect:EventEmitter<any> = new EventEmitter();
data:any = {text: "example"};
constructor(private router:Router){}
changeComponent(url:string){
this.redirect.emit(data);//emits the data to the parent
this.router.navigate([url]);//redirects url to new component
}
}
Component2 & Component3
import { Component, Input } from '@angular/core';
@Component(...)
export class Component2 {
@Input() data:any;
}
Parent
import { Component } from '@angular/core';
@Component(...)
export class Parent {
parentData:any;
}
Parent.html
<component1 (redirect)="parentData=$event"></component1>
<component2 [data]="parentData"></component2>
<component3 [data]="parentData"></component3>
Another option, if you don't have a parent, is to have a service, that you inject into each parent, and then for the receivers hook into the OnInit lifecycle hook. This works because services are a singleton if in a provider of a shared module.
Service
import { Injectable } from '@angular/core';
@Injectable()
export class SharingService{
private data:any = undefined;
setData(data:any){
this.data = data;
}
getData():any{
return this.data;
}
}
Component1
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { SharingService } form './sharing.service';
@Component(...)
export class Component1 {
data:any = {text: "example"};
constructor(private router:Router,
private sharingService:SharingService){}
changeComponent(url:string){
this.sharingService.setData(this.data);
this.router.navigate([url]);//redirects url to new component
}
}
Component2 & Component3
import { Component, OnInit } from '@angular/core';
import { SharingService } form './sharing.service';
@Component(...)
export class Component2 implements OnInit{
data:any;
constructor(private router:Router,
private sharingService:SharingService){}
ngOnInit(){
this.data = this.sharingService.getData();
}
}
Make sure you add it to providers array of the module.
Module
import { SharingService } from './sharing.service';
...
@NgModule({
...
providers: [ SharingService ]
})
Answer from Joo Beck on Stack OverflowAs it looks like you are looking to redirect to those components, what you can do is have an event emitter on component one, that on click will emit the data to the parent(of all 3). Then in the parent you would catch the emit, and assign that to data that you pass into the other components.
Component1
import { Component, EventEmitter, Output } from '@angular/core';
import { Router } from '@angular/router';
@Component(...)
export class Component1 {
@Output() redirect:EventEmitter<any> = new EventEmitter();
data:any = {text: "example"};
constructor(private router:Router){}
changeComponent(url:string){
this.redirect.emit(data);//emits the data to the parent
this.router.navigate([url]);//redirects url to new component
}
}
Component2 & Component3
import { Component, Input } from '@angular/core';
@Component(...)
export class Component2 {
@Input() data:any;
}
Parent
import { Component } from '@angular/core';
@Component(...)
export class Parent {
parentData:any;
}
Parent.html
<component1 (redirect)="parentData=$event"></component1>
<component2 [data]="parentData"></component2>
<component3 [data]="parentData"></component3>
Another option, if you don't have a parent, is to have a service, that you inject into each parent, and then for the receivers hook into the OnInit lifecycle hook. This works because services are a singleton if in a provider of a shared module.
Service
import { Injectable } from '@angular/core';
@Injectable()
export class SharingService{
private data:any = undefined;
setData(data:any){
this.data = data;
}
getData():any{
return this.data;
}
}
Component1
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { SharingService } form './sharing.service';
@Component(...)
export class Component1 {
data:any = {text: "example"};
constructor(private router:Router,
private sharingService:SharingService){}
changeComponent(url:string){
this.sharingService.setData(this.data);
this.router.navigate([url]);//redirects url to new component
}
}
Component2 & Component3
import { Component, OnInit } from '@angular/core';
import { SharingService } form './sharing.service';
@Component(...)
export class Component2 implements OnInit{
data:any;
constructor(private router:Router,
private sharingService:SharingService){}
ngOnInit(){
this.data = this.sharingService.getData();
}
}
Make sure you add it to providers array of the module.
Module
import { SharingService } from './sharing.service';
...
@NgModule({
...
providers: [ SharingService ]
})
Since you have asked to share the data between sibling components we can achieve it by using BehaviourSubject in service.
The BehaviorSubject holds the value that needs to be shared with other components. These components subscribe to data which is simple returning the BehaviorSubject value without the functionality to change the value.
Service.ts
import { Observable, BehaviorSubject } from 'rxjs';
export class Service {
private data = new BehaviorSubject("")
currentData = this.data.asObservable();
constructor() { }
setData(data) {
this.data.next(data);
}
Component1.ts
import { Service } from '../service.service';
export class component1 implements OnInit {
data: any;
constructor (private service: Service) {}
sendDataToService() {
this.service.setData(this.data);
}
Component2.ts
import { Service } from '../../service.service';
export class component2 implements OnInit {
constructor ( private service: Service ) { }
ngOnInit() {
this.service.currentData.subscribe(data => {
console.log(data);
});
}
Angular 2 Sibling Component Communication
angular - How to pass data to an exact sibling component? - Stack Overflow
routes - How can I pass data between sibling components in Angular? - Stack Overflow
Share data between sibling components
I tend to use Subjects via services:
https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/
I'm sure there are other ways of doing this but the above tutorial is very straight forward and covers different types of component relationships.
More on reddit.comVideos
Updated to rc.4: When trying to get data passed between sibling components in angular 2, The simplest way right now (angular.rc.4) is to take advantage of angular2's hierarchal dependency injection and create a shared service.
Here would be the service:
import {Injectable} from '@angular/core';
@Injectable()
export class SharedService {
dataArray: string[] = [];
insertData(data: string){
this.dataArray.unshift(data);
}
}
Now, here would be the PARENT component
import {Component} from '@angular/core';
import {SharedService} from './shared.service';
import {ChildComponent} from './child.component';
import {ChildSiblingComponent} from './child-sibling.component';
@Component({
selector: 'parent-component',
template: `
<h1>Parent</h1>
<div>
<child-component></child-component>
<child-sibling-component></child-sibling-component>
</div>
`,
providers: [SharedService],
directives: [ChildComponent, ChildSiblingComponent]
})
export class parentComponent{
}
and its two children
child 1
import {Component, OnInit} from '@angular/core';
import {SharedService} from './shared.service'
@Component({
selector: 'child-component',
template: `
<h1>I am a child</h1>
<div>
<ul *ngFor="#data in data">
<li>{{data}}</li>
</ul>
</div>
`
})
export class ChildComponent implements OnInit{
data: string[] = [];
constructor(
private _sharedService: SharedService) { }
ngOnInit():any {
this.data = this._sharedService.dataArray;
}
}
child 2 (It's sibling)
import {Component} from 'angular2/core';
import {SharedService} from './shared.service'
@Component({
selector: 'child-sibling-component',
template: `
<h1>I am a child</h1>
<input type="text" [(ngModel)]="data"/>
<button (click)="addData()"></button>
`
})
export class ChildSiblingComponent{
data: string = 'Testing data';
constructor(
private _sharedService: SharedService){}
addData(){
this._sharedService.insertData(this.data);
this.data = '';
}
}
NOW: Things to take note of when using this method.
- Only include the service provider for the shared service in the PARENT component and NOT the children.
- You still have to include constructors and import the service in the children
- This answer was originally answered for an early angular 2 beta version. All that has changed though are the import statements, so that is all you need to update if you used the original version by chance.
In case of 2 different components (not nested components, parent\child\grandchild ) I suggest you this:
MissionService:
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class MissionService {
// Observable string sources
private missionAnnouncedSource = new Subject<string>();
private missionConfirmedSource = new Subject<string>();
// Observable string streams
missionAnnounced$ = this.missionAnnouncedSource.asObservable();
missionConfirmed$ = this.missionConfirmedSource.asObservable();
// Service message commands
announceMission(mission: string) {
this.missionAnnouncedSource.next(mission);
}
confirmMission(astronaut: string) {
this.missionConfirmedSource.next(astronaut);
}
}
AstronautComponent:
import { Component, Input, OnDestroy } from '@angular/core';
import { MissionService } from './mission.service';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector: 'my-astronaut',
template: `
<p>
{{astronaut}}: <strong>{{mission}}</strong>
<button
(click)="confirm()"
[disabled]="!announced || confirmed">
Confirm
</button>
</p>
`
})
export class AstronautComponent implements OnDestroy {
@Input() astronaut: string;
mission = '<no mission announced>';
confirmed = false;
announced = false;
subscription: Subscription;
constructor(private missionService: MissionService) {
this.subscription = missionService.missionAnnounced$.subscribe(
mission => {
this.mission = mission;
this.announced = true;
this.confirmed = false;
});
}
confirm() {
this.confirmed = true;
this.missionService.confirmMission(this.astronaut);
}
ngOnDestroy() {
// prevent memory leak when component destroyed
this.subscription.unsubscribe();
}
}
Source: Parent and children communicate via a service
You can use service for shared data. If you have complex use case, that the data is used everywhere and many components can make changes, then manybe you should consider state management process like redux.
Matteo the best solution for me is used the Subject. The logic are these:
- Create the Subject in the father's
ngOnInit()( create the channel) - Pass the Subject to siblings ( sign in the siblings in the channel)
- In sibling's ngOnInit() you can register the sibling in to the channel
- when you click on checkout yuou can notify the component that are listening in the channel with the total amout.
- destroy channel and unregister the component