I have multiple grids in a view and when the user drags on the scrollbar of one grid I want it to automatically scroll the other grids exactly the same amount up or down.
So in my ngAfterViewInit() method I have the following:
document.querySelector(".k-grid .k-grid-content").addEventListener("scroll", (e) => {
console.log('scroll event', e);
}
The idea is that I can then capture this event and pass it to the other grids so they can scroll too. However this isn't working as the event listener doesn't fire. Can you suggest a way to make this work?
2 Answers, 1 is accepted
I've gotten this working for syncing both scrolling and row hovering. In my implementation, your grid component ("app-my-data-grid") should implement IElementRef:
@Component({
selector: 'app-my-data-grid',
template: `<kendo-grid ...></kendo-grid>`,
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
styles: [`
app-my-data-grid .hide-scrollbar > * {
margin-right: -7px;
}
`]
})
export class MyDataGridComponent implements AfterViewInit, IElementRef {
@Input() data: any[];
@Input() hideScrollbar: boolean = true;
@Output() contentScroll: EventEmitter<ContentScrollEvent>; //The event we'll listen to
@ViewChild(GridComponent, { static: true }) gridEl: GridComponent; //Our actual kendo grid reference
public element: Element; //Part of IElementRef, so the sync functions have something to reference
constructor(elRef: ElementRef) {
this.element = elRef.nativeElement;
}
ngAfterViewInit(): void {
this.contentScroll = this.gridEl.contentScroll; //use the kendo grid's native scroll event
}
// your logic ...
}
<app-grid-sync [gridDataChanged]="dataChange$ | async">
<app-my-data-grid
*ngFor="let gridDataSet of dataSet; last as isLast"
[data]="gridDataSet"
[hideScrollbar]="!isLast">
</app-my-data-grid>
</app-grid-sync>
This will assigns the array of grids to a scroll sync set and a hover sync set. These "sets" manage the events from the element the user is scrolling/hovering on and syncs that to the others.
The actual event listeners are in ScrollSet and HoverSet. The factories aren't that helpful. They really just provide ngZone. As for the names of the events being listened to, those are in the grid-sync directive near the bottom:
private setScrollSync(grids) {
this.clearScrollSync();
if (!grids?.length) {
return;
}
this.elementSubs = this._scrollSyncFactory.syncVerticalScroll(grids, "contentScroll", "k-grid-content");
}
private setHoverSync(grids) {
this.clearHoverSync();
if (!grids?.length) {
return;
}
setTimeout(() => { //If I remember correctly, this allows the tr elements time to be created. Might be better to use a MutationObserver
this.hoverSubs = this._hoverSyncFactory.syncHover(grids, ".k-grid-content tr", ["k-state-hover", "hover"]);
}, 0);
}
Hey @Christopher, I've been working a week trying to do that and now I find your implementation, and from @Murray's feedback its look like working!
Can you help me a bit with that, I saw the files and try to implement them, but maybe I'm missing something here.
I added the files and interface, and imported everything, it is building but I'm not able to find why it's not working, maybe missing the difference between the grid-component and usage-component files you posted.
Appreciate any help!