0

I am trying to have a component change and access the variables of another component (sibling components, without a child/parent relationship). I want to do this via querySelecting the components by a particular class name, and then getting the component reference from its HTML tag.

For instance, say there are 3 Response components, 2 of which have the class "group-1" and 1 which has "group-2", and a Trigger component. These are all sibling components.

From the Trigger component, I want to be able to access the 2 Response components that have the class "group-1".

Currently, I have:

Within Trigger Component:

const group1ResponseComponents = document.querySelectorAll(".group-1");
forEach((response: Element) => {
    let responseComponent = response. ???? (get the Component Ref from its HTML)
    responseComponent.varA = true;
});

I can get the ... component HTML, but how do I actually get the component? Vue has something like '.__vue__' to from the native element to the component. I can't really use ViewChildren or ContentChildren in this scenario since they are sibling components. Any ideas?

ACarr
  • 89
  • 6
  • If you need to communicate between two siblings components, you have to implement a shared service that provide a Stream of communication. [this link can help you](https://stackoverflow.com/questions/35884451/angular-2-sibling-component-communication) – Saif Jerbi Sep 10 '19 at 21:06

2 Answers2

0

As the others have suggested you should use a service injected into the sibling components to manage this.

import { Injectable } from "@angular/core";
import { Subject, Observable } from "rxjs";

export interface ISharedServiceEvent {
  sourceId: string;
  data: any;
}

@Injectable()
export class SharedService {

  private subject: Subject<ISharedServiceEvent> = new Subject<ISharedServiceEvent>();

  constructor() {
  }

  get observable(): Observable<ISharedServiceEvent> {
    return this.subject.asObservable();
  }

  public emitEvent(event: ISharedServiceEvent) {
    this.subject.next(event);
  }

}

Your sibling components should subscribe to sharedService.observable and handle the events as needed. Make sure you unsubscribe from the subscription when your component is destroyed. Emit events whenever you want to pass data to another sibling.

Noremac
  • 554
  • 2
  • 7
0

You need to create a shared service. Once you create a share service you need to use declarative variables. We are being more reactive now, we are on Angular. Forget about having get() methods everywhere.

Here's why:

You see what I did I got rid of the method and here's why:

-Leverage the power of rxjs observables and operators

-effectively compatible streams

-easy share observables

-readily react to user action

@Deborah Kurata mentioned this in his RxJS course (she is a GDE on Angular)

export class SharedService {

  private dataSubject: Subject<ISharedServiceEvent> = new Subject<ISharedServiceEvent>();
  data$ = this.subject.asObservable();

  constructor() {
  }

 emitEvent(event: ISharedServiceEvent) {
    this.subject.next(event);
  }

}

No need to mention the world 'public' since it's inferred.

In you components now you can do the following:

constructor(private sharedService: SharedService){}

data$ = this.sharedService.data$;

//or
data: any;//using any for example purposes
this.sharedService.data$.subscribe(d => this.data = d);

HTML you can use the async pipe

{{data$ | async | json}} //json pipe for showing purposes

NOTE IF YOU SUBCRIBE MANUALLY. You have to unsubscribe in the ngOnDestroy()

Patricio Vargas
  • 5,236
  • 11
  • 49
  • 100