Angular 4 scroll two seperate elements togther

Angular CDK now provides cdkScrollable and ScrollDispatcher. Just add cdkScrollable directive to all your scrollable elements which need to be kept in sync and then add this logic to your component:

this.scrollDispatcher.scrolled().subscribe((scrollable: CdkScrollable) => {
  if (typeof scrollable == 'undefined') {
    return true;
  }
  const left = scrollable.measureScrollOffset('left');

  Array.from(this.scrollDispatcher.scrollContainers.keys())
    .filter(otherScrollable => otherScrollable && otherScrollable !== scrollable)
    .forEach(otherScrollable => {
      if (otherScrollable.measureScrollOffset('left') !== left) {
        otherScrollable.scrollTo({left});
      }
    });
});

Do not forget to unsubscribe from this subscription when the component is destroyed. And also inject ScrollDispatcher service in the constructor:

public constructor(private scrollDispatcher: ScrollDispatcher) {}

You can just get a reference to the second <div> and set it's scroll left to the same amount:

<div class="container" (scroll)="scrollTwo.scrollLeft = scrollOne.scrollLeft" #scrollOne>
    ...
</div>
<div class="container" #scrollTwo>
    ...
</div>

If you want to have more complicated logic in your component to manage what the scroll amount should be, you can just get the reference to the two DOM nodes via @ViewChild:

<div class="container" (scroll)="updateScroll()" #scrollOne>
    ...
</div>
<div class="container" #scrollTwo>
    ...
</div>
@Component(...)
export class AppComponent  {
  @ViewChild('scrollOne') scrollOne: ElementRef;
  @ViewChild('scrollTwo') scrollTwo: ElementRef;

  updateScroll(){
    const scrollOne = this.scrollOne.nativeElement as HTMLElement;
    const scrollTwo = this.scrollTwo.nativeElement as HTMLElement;

    // do logic and set
    scrollTwo.scrollLeft = scrollOne.scrollLeft;
  }
}

You don't have to get the references via @ViewChild. You could rather just pass them into the method that is called:

<div class="container" (scroll)="updateScroll(scrollOne, scrollTwo)" #scrollOne>
    ...
</div>
<div class="container" #scrollTwo>
    ...
</div>
@Component(...)
export class AppComponent  {
  updateScroll(scrollOne: HTMLElement, scrollTwo: HTMLElement){
    // do logic and set
    scrollTwo.scrollLeft = scrollOne.scrollLeft;
  }
}

Tags:

Angular