I have a demo here
I'm capturing the scrollLeft
of one element as it's scrolled.
Is it possible to update the second div with the scrollLeft
number so both div scroll left and right together?
The elements have to be separate but I need them to scroll together.
Or is there a simpler way to do this in Angular.
I had this working outside of Angular with jQuery but I don't want to use jQuery in Angular.
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular 5';
isNavbarCollapsed = true;
private scrollLeft: number
//private scrolLTwo: HTMLElement =
onScroll(event: Event) {
this.scrollLeft = (event.target as HTMLElement).scrollLeft;
//console.log(this.scrollLeft);
this.updateScroll();
}
updateScroll(){
//Update second scrolling element
}
}
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;
}
}
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) {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With