swimlane / ngx-datatable

✨ A feature-rich yet lightweight data-table crafted for Angular
http://swimlane.github.io/ngx-datatable/
MIT License
4.63k stars 1.68k forks source link

Header scrolls horizontally but body doesn't follow with header scroll #2143

Open mmfKupl opened 1 year ago

mmfKupl commented 1 year ago

I'm submitting a ... (check one with "x")

[x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, post on Stackoverflow or Gitter

Current behavior

The entire header row scrolls horizontally, but the body scroll does not change.

Expected behavior

The entire header row and body should scroll horizontally together.

Reproduction of the problem

  1. Create a table.
  2. Add a custom header template with an input component.
  3. Set scrollbarH to true.
  4. Make the table scrollable horizontally.
  5. Focus on the first input in the header.
  6. Press the "TAB" key to change the focus to the next input.

See example in stackblitz editor or app

I have examined the source code of ngx-datatable and found that there is no header-to-body scrolling synchronization, only body-to-header scrolling. I attempted to listen to the header scroll event and recalculate the table dimensions but was not successful.

What is the motivation / use case for changing the behavior?

The motivation for changing the behavior is to allow for the addition of inputs and other elements to the header for expanding table functionality.

Please tell us about your environment:

mmfKupl commented 1 year ago

I have found a solution that works for me:

I listen to a scroll event on the header element and reset the scroll position to the beginning. Additionally, I listen to a focus event from the header element and scroll the table body to it.

  ngOnInit() {
      const headerElement: HTMLElement = this.hostElementRef.nativeElement.querySelector('.datatable-header');
      // prevent horizontal scroll on header element and table element
      headerElement.addEventListener('scroll', this.scrollEventListener.bind(this));
      // on each focus event we have to scroll the body to this element
      headerElement.addEventListener('focus', this.focusEventListener.bind(this), true);
  }

  private scrollEventListener(scrollEvent: Event): void {
    if (this.skipScroll) {
      this.skipScroll = false;
      return;
    }
    this.skipScroll = true;
    (scrollEvent.target as HTMLElement).scrollTo({ left: 0 });
  }

    private focusEventListener(event: FocusEvent): void {
    const ngxDatatableBodyElement: HTMLElement = this.hostElementRef.nativeElement.querySelector(
      'ngx-datatable .datatable-body',
    );
    const bodyClientRect: DOMRect = ngxDatatableBodyElement.getBoundingClientRect();
    const targetClientRect: DOMRect = (event.target as HTMLElement).getBoundingClientRect();

    const gap: number = 8;
    const isLeftOut: boolean = targetClientRect.left < bodyClientRect.left + gap;
    const isRightOut: boolean = targetClientRect.right > bodyClientRect.right - gap;
    if (isLeftOut || isRightOut) {
      let scrollLeft: number;
      if (isLeftOut) {
        scrollLeft = ngxDatatableBodyElement.scrollLeft - bodyClientRect.left + targetClientRect.left - gap;
      } else {
        scrollLeft = ngxDatatableBodyElement.scrollLeft - bodyClientRect.right + targetClientRect.right + gap;
      }

      ngxDatatableBodyElement.scrollTo({ left: scrollLeft });
    }
  }

I have added a fixed example to StackBlitz, but it is not working well, and I don't have time to figure out why at the moment

baarbaracrr commented 5 months ago

The same happens to me. I move the horizontal scroll of the body of the table, but the header does not follow it and stays where it was. This happens to me in Firefox.

BrianMcGrathOtised commented 4 months ago

This seems to only happen in Firefox.

mmfKupl commented 4 months ago

@BrianMcGrathOtised Recently, I encountered another bug with scrolling in Firefox where the body scrolls, but the header does not follow the scroll position.

This issue started occurring in Firefox 125 because they removed support for vendor-prefix properties. You can read more about it here: https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Experimental_features#vendor-prefixed_transform_properties

The ngx-datatable library uses these prefixes for translating the header component.

May be you have faced this issue.

GauravKediaDbox commented 1 month ago

@mmfKupl Thanks for the info, but how did you fix the issue then ?

mmfKupl commented 1 month ago

@GauravKediaDbox

@mmfKupl Thanks for the info, but how did you fix the issue then ?

I use a fork ngx-datatabe in my project and changed this file so that prefixes are not added.

Instead of forking, you can patch the package using patch-package - it's worked for me well for about 2 years.