简体   繁体   中英

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. Ie- 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.

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);
  }


}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM