MarkD
MarkD

Reputation: 4944

Accessing an element from sibling component in Angular 2+

I have a set of components that work together. Basically I am displaying a list of labels, and a list of data for each label. Since the label pane is resizable, it becomes a sibling of the data component. I.e.- my list component looks like:

<app-list-labels></app-list-labels>
<app-list-data></app-list-data>

And list-labels and list-data look like this, respectively:

// app-list-labels:
<div class="label-header">Labels</div>
<div class="label-labels" id="labels-labels">
   <!-- all of my labels looped over and displayed -->
</div>

// app-list-data:
<div class="data-header">Labels</div>
<div class="data-data" id="data-data">
   <!-- all of my data rows looped over and displayed -->
</div>

Both labels-labels and data-data have overflow-y set to auto, so that they can scroll if the number of rows exceeds the container size. The number and size of rows between the two are always identical. My goal is to have both containers scroll if one container is being scrolled. So I'd need to attach a (scroll) event listener to both of those divs (#data-data and #labels-labels), and update the scroll value of the non-scrolled element. My problem is- how can I access an element from one component in a sibling component? If app-labels was embedded in app-data it would be straight forward, but being siblings, I cant see how to do it.

Upvotes: 0

Views: 3424

Answers (1)

Gabriel Lopez
Gabriel Lopez

Reputation: 452

You could try exposing the Div's using @Output decoratos, like this:

<app-component-one (divComponent)="divOne = $event"></app-component-one>
<app-component-two (divComponent)="divTwo = $event"></app-component-two>

Sibling 1:

import { AfterViewInit, Component, ElementRef, EventEmitter, OnInit, Output, ViewChild } from '@angular/core';

@Component({
  selector: 'app-component-one',
  templateUrl: './component-one.component.html',
  styleUrls: ['./component-one.component.css']
})
export class ComponentOneComponent implements OnInit, AfterViewInit {

  @ViewChild('divComponent1') divComponent1: ElementRef;
  @Output() divComponent = new EventEmitter();

  constructor() {
  }

  ngOnInit() {
  }

  ngAfterViewInit(): void {
    this.divComponent.emit(this.divComponent1);
  }


}

Sibling 2:

import { AfterViewInit, Component, ElementRef, EventEmitter, OnInit, Output, ViewChild } from '@angular/core';

@Component({
  selector: 'app-component-two',
  templateUrl: './component-two.component.html',
  styleUrls: ['./component-two.component.css']
})
export class ComponentTwoComponent implements OnInit, AfterViewInit {

  @ViewChild('divComponent2') divComponent1: ElementRef;
  @Output() divComponent = new EventEmitter();

  constructor() {
  }

  ngOnInit() {
  }

  ngAfterViewInit(): void {
    this.divComponent.emit(this.divComponent1);
  }

}

Parent Component, the one that has the siblings in :

import { AfterViewInit, Component, ElementRef, OnInit } from '@angular/core';

@Component({
  selector: 'app-component-base',
  templateUrl: './component-base.component.html',
  styleUrls: ['./component-base.component.css']
})
export class ComponentBaseComponent implements OnInit, AfterViewInit {

  divOne: ElementRef;
  divTwo: ElementRef;

  constructor() {
  }

  ngOnInit() {
  }

  ngAfterViewInit(): void {
    console.log('div one' , this.divOne);
    console.log('div two' , this.divTwo);
  }


}

Upvotes: 1

Related Questions