I have two custom-component
s that are spawned by a common parent with different data as two tabs on mat-tab-group
.
<mat-tab-group>
<mat-tab label="TAB1">
<ng-template matTabContent>
<custom-component [data]="tab1data"></custom-component>
</ng-template>
</mat-tab>
<mat-tab label="TAB2">
<ng-template matTabContent>
<custom-component [data]="tab2data"></custom-component>
</ng-template>
</mat-tab>
</mat-tab-group>
The data
is a setter that sets the internal _data
and wraps it in MatTableDataSource
:
@Input()
set data(val: Data[]) {
this._data = val;
this.loadData();
}
loadData(): void {
this.dataSource = new MatTableDataSource<Data>(this._data);
this.dataSource.sort = this.sort;
}
I have a situation where actions for component on the first tab should affect data on the other tab.
Is there any way to pass component references, so I could change _data
and call loadData()
from other component?
You can do this with Rxjs observables
Here is stackblitz example of how to communicate between two components https://stackblitz.com/edit/angular-ivy-myr2kh
my-service.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable()
export class MyServiceService {
private dataChangeObservable = new Subject<any>();
dataChangeStream = this.dataChangeObservable.asObservable();
constructor() { }
emitDataChange() {
this.dataChangeObservable.next();
}
}
ComponentOne.component.ts
onclickDiv() {
this.myService.emitDataChange(); // Here you are triggering for change
}
ComponentTwo.component.ts
ngOnInit() {
this.dataChangeSubscription$ = this.myService.dataChangeStream.subscribe(() => {
this.count++; // Here you will get notified/listener of change
})
}
Update
If you have same component instances, then you have to pass some value to determine on which instance should get updated
Like
https://stackblitz.com/edit/angular-ivy-4pznor
Your parent html
<app-componentone [name]="'one'"></app-componentone>
<app-componentone [name]="'two'"></app-componentone>
Here one
and two
pass as an input to just to identify the instance
Then your ts
import { Component, OnInit, Input } from '@angular/core';
import { MyServiceService } from '../my-service.service';
@Component({
selector: 'app-componentone',
templateUrl: './componentone.component.html',
styleUrls: ['./componentone.component.css']
})
export class ComponentoneComponent implements OnInit {
@Input() name; // it will have instance name
count = 0;
constructor(
private myService: MyServiceService
) { }
ngOnInit() {
this.myService.dataChangeStream.subscribe((value) => { // here we will get to notify which instance should get updated
if (this.name !== value) { // Here we checking for instance name for updating, if same component instance don't do anything else update
this.count++;
}
})
}
onclickDiv() {
// Here I am passing parameter, so if click is triggered from instance one, we have to update other instances, so passing parameter 'one' i.e. name, to avoid updating same component instance
this.myService.emitDataChange(this.name);
}
}