Обмен ссылками между двумя компонентами одного уровня - PullRequest
0 голосов
/ 29 мая 2020

У меня есть два custom-component s, которые порождены общим родителем с разными данными в виде двух вкладок на 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>

data - это сеттер, который устанавливает внутренний _data и оборачивает его в 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;
}

У меня есть ситуация, когда действия для компонента на первая вкладка должна влиять на данные на другой вкладке. Есть ли способ передать ссылки на компоненты, чтобы я мог изменить _data и вызвать loadData() из другого компонента?

Ответы [ 2 ]

1 голос
/ 03 июня 2020

Вы можете сделать это с помощью Rx js наблюдаемых

Вот пример stackblitz того, как взаимодействовать между двумя компонентами 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
    })
 }

Обновление

Если у вас есть одинаковые экземпляры компонентов, вам нужно передать какое-то значение, чтобы определить, какой экземпляр должен обновляться

Like

https://stackblitz.com/edit/angular-ivy-4pznor

Ваш родитель html

<app-componentone [name]="'one'"></app-componentone>
<app-componentone [name]="'two'"></app-componentone>

Здесь one и two передаются как входные данные, чтобы просто идентифицировать экземпляр

Тогда ваш 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);
  }
}
0 голосов
/ 03 июня 2020
• 1000 -
this.dataChange.emit('changed data');

В родительском компоненте, где находится селектор этого компонента, измените селектор на: -

HTML: -

<custom-component [data]="tab1data" (dataChange)="modifyDataTab2($event)"></custom-component>

TS: -

modifyDataTab2(firstTabData) {
   this.tab2Data = firstTabData;
   // or you can make other changes.
} 

Теперь, поскольку tab2 уже имеет tab2Data в качестве входных данных, ваш loadData () будет вызываться автоматически.

Если вы хотите изменить данные вкладки 1 на вкладке 2, не нужно снова изменять компонент вкладки, каждый экземпляр будет иметь свой собственный вывод. изменение будет только в родительском. это будет: -

HTML: -

<custom-component [data]="tab2data" (dataChange)="modifyDataTab1($event)"></custom-component>

TS: -

modifyDataTab1(secondTabData) {
   this.tab1Data = secondTabData;
   // or you can make other changes.
} 

Это преимущество наличия общего родителя. если два ребенка хотят общаться, они должны делать это через родителя. потому что любое изменение данных в родительском элементе, которое передается в качестве входных данных, автоматически инициирует необходимые изменения в дочернем элементе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...