ngx-datatable icon indicating copy to clipboard operation
ngx-datatable copied to clipboard

Datatable width resize problem. datatable-scroller and datatable-header-inner does not resize after initial load

Open webmatrixxxl opened this issue 6 years ago • 26 comments

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

[x] bug report => search github for a similar issue or PR before submitting

Current behavior datatable-scroller and datatable-header-inner(also it's children) doesn't resize on width after datatable inital load

Expected behavior They should resize... https://cl.ly/1U090c3Q0X2S

Reproduction of the problem You can represent the problem anywhere.

What is the motivation / use case for changing the behavior? This is a bug.

Please tell us about your environment: macOS Sierra, Chrome Version 60.0.3112.101

  • Table version: 9.3.0, 10.0.5

  • Angular version: 4.3.3

  • Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]

  • Language: [all | TypeScript X.X | ES6/7 | ES5]

webmatrixxxl avatar Aug 21 '17 15:08 webmatrixxxl

I have also encountered this. Some things I've tried is to trigger recalculate table but that does not fix the problem.

katestearns-suplari avatar Aug 22 '17 21:08 katestearns-suplari

Same here. After ngShow/ngIf the table didn't recalculate columns width until viewport resize event is manually triggered.

DavideRoss avatar Sep 04 '17 09:09 DavideRoss

The ngx-datatable also doesn't recalculate height in the same situation, if data updates while the table is not visible it decides each virtual page can only contain a single row. You get a messed up view until the table is resized through e.g. a browser window resize.

insidewhy avatar Nov 13 '17 12:11 insidewhy

Here's a hack I implemented in the component containing the datatable:

    this.cd.markForCheck();
    setTimeout(() => {
        document.body.style.width = window.innerWidth - 1 + 'px';
        this.table.recalculate();
        this.table['cd'].markForCheck();
        document.body.style.width = 'auto';
    }, 0);

BBaysinger avatar Jan 29 '18 21:01 BBaysinger

The hack in my previous comment isn't actually reliable. The only way to fix this problem is to revert to v10.5.0. Please fix this.

BBaysinger avatar Feb 01 '18 23:02 BBaysinger

@webmatrixxxl Hi i have simple solution for this. You just need to trigger window resize event.

window.dispatchEvent(new Event('resize'));

ahmetacer5 avatar Apr 01 '18 17:04 ahmetacer5

@webmatrixxxl I tried that once and it worked, but the last time I tried, didn’t work.

BBaysinger avatar Apr 01 '18 21:04 BBaysinger

Here i found a hack for "datatable-scroller" resize issue...

Ngx-Datatable version which i am using right now

"@swimlane/ngx-datatable": "11.1.7",

setTimeout(() => {
                 $('#mainNgxTable .datatable-scroll').width('100%');
}, (500));

#mainNgxTable id of ngx-datatable,

<ngx-datatable id="mainNgxTable" ... >

it is best if you call this init data/rows for ngx-datatable

I am doing in Angualr 2

this.dataService
                .getData()
                .subscribe(
                    data => {
                            this.rows = data.rows; // init or loading data, came in response of restApi call
                            setTimeout(() => {
                                $('#mainNgxTable .datatable-scroll').width('100%');
                            }, (500));
                    },
                    error => {
                        //handle error
                    }
                );

ArfanMirza avatar Jun 21 '18 12:06 ArfanMirza

Well

It seems that the scroller width is calculated in the body.component.ts file

@Input() set columns(val: any[]) {
    this._columns = val;
    const colsByPin = columnsByPin(val);
    this.columnGroupWidths = columnGroupWidths(colsByPin, val);
  }

Now this.columnGroupWidths dictates the width of the scroller and this is sadly not recalculated on ngxDatatable.recalculate(); function.

What I did is every time I want to recalculate I firstly reset the columns pointer in the datatable and then recalculate. Seemed to fix the issue for me!

component.ts

class X {
@ViewChild(DatatableComponent) ngxDatatable: DatatableComponent;

recalculate() {
        this.columns = [...this.columns]; //This is input into <ngx-datatable>
        this.ngxDatatable.recalculate(); //ngx-datatable reference
    }
...
}

component.html

<ngx-datatable
        [columns]="columns"
        [rows]="rows">
</ngx-datatable>

karljv avatar Jul 05 '18 23:07 karljv

columnGroupWidths

can you show us how you did that?, did you create a recalculate function ?

GRTO avatar Oct 11 '18 16:10 GRTO

I used the recalculate function on DatatableComponent

@ViewChild(DatatableComponent) datatable: DatatableComponent;

karljv avatar Oct 14 '18 06:10 karljv

Adding a simple css rule for .datatable-scroll display: inherit !important; works for me

GevorgGabrielyan avatar Nov 05 '18 11:11 GevorgGabrielyan

I had similar problem with the table width not changing properly after mobile device screen rotations. @karljv solution works for me. I also use a rotation change host listener to trigger the recalculation:

@HostListener('window:orientationchange', ['$event']) onOrientationChange(event) { ... }

appagg avatar Jan 18 '19 08:01 appagg

I have tried all possible approaches and end up disabling scrolling and implementing paging ... it worked for me Ex: //scrollX: "99.95%", //scrollY: 300, paging: true,

jrodg avatar Apr 03 '19 18:04 jrodg

Is this still an open issue for everyone? I am running into a similar issue with the latest release and was wondering what the recommended workaround is or if anyone has a fork that fixes up the issue. (cc @marjan-georgiev in case there is a fix already in place from another issue)

abierbaum avatar Jul 07 '19 14:07 abierbaum

This is not a solution that I would like, but to temporarily fix it, what I do is the following:

component.html


<mat-tab-group (selectedIndexChange)="isAnimationDone= false" (animationDone)="isAnimationDone= true;">
    <mat-tab>
        <ngx-datatable class="material" [rows]="licenses"  *ngIf="isAnimationDone">
            ...
            ...
            ...
        </ngx-datatable> 
    </mat-tab>
</mat-tab-group>

component.ts

isAnimationDone: boolean = true;

@HostListener('window:resize', ['$event'])
onResize(event){
    this.isAnimationDone=false;
    setTimeout(() =>this.isAnimationDone=true, 1000);
}

leon99adolfo avatar Apr 23 '20 19:04 leon99adolfo

@ViewChild("table") table: DatatableComponent;

@HostListener('window:resize', ['$event']) onResize(event) { this.table.recalculate(); this.table.recalculateColumns(); }

This works for me.

meenu1 avatar May 05 '20 12:05 meenu1

@webmatrixxxl Hi i have simple solution for this. You just need to trigger window resize event.

window.dispatchEvent(new Event('resize'));

ngAfterViewChecked():void{ window.dispatchEvent(new Event('resize')); }

it works!

codingnut avatar Aug 11 '20 07:08 codingnut

Here's a hack I implemented in the component containing the datatable:

    this.cd.markForCheck();
    setTimeout(() => {
        document.body.style.width = window.innerWidth - 1 + 'px';
        this.table.recalculate();
        this.table['cd'].markForCheck();
        document.body.style.width = 'auto';
    }, 0);

The problem with this approach is that if you have a filtering table, i.e. a search functionality on the table, the search feature breaks.

UsmanMajied17 avatar Aug 17 '20 10:08 UsmanMajied17

These classes worked for me without adding any hooks or resize method.

.datatable-header-inner{ width: 100% !important; }

.datatable-scroll{ display: inherit !important; }

.datatable-row-center{ width: 100% !important; }

.datatable-body-row{ width: 100% !important; }

manjeetyadv avatar Aug 23 '20 09:08 manjeetyadv

@webmatrixxxl Hi i have simple solution for this. You just need to trigger window resize event.

window.dispatchEvent(new Event('resize'));

This worked for me

rishi1305 avatar Dec 07 '20 12:12 rishi1305

@webmatrixxxl Hi i have simple solution for this. You just need to trigger window resize event.

window.dispatchEvent(new Event('resize'));

I have made so many try but this things works for me. Thank you.

dp1127 avatar Jun 10 '21 18:06 dp1127

window.dispatchEvent(new Event('resize'));

this one work with me many thanks

buiquanghungOU avatar Aug 06 '21 06:08 buiquanghungOU

I had a similar problem and it was resolved thanks to everyone.


Create a directive that detects width differences and raises a resize event

import { Directive, AfterContentChecked } from '@angular/core';
import { DatatableComponent } from '@swimlane/ngx-datatable';

@Directive({ selector: '[appNgxTableResizer]' })
export class NgxTableResizerDirective implements AfterContentChecked {
  constructor(private table: DatatableComponent) {}

  ngAfterContentChecked(): void {
    const timerId = setInterval(() => {
      if (this.table && this.table.element.clientWidth !== this.table._innerWidth) {
        window.dispatchEvent(new Event('resize'));
      } else {
        clearInterval(timerId);
      }
    }, 100);
  }
}

set directive

  <ngx-datatable
    appNgxTableResizer
    ...>
  </ngx-datatable>

load module

@NgModule({
  declarations: [XXXComponent, NgxTableResizerDirective],
  exports: [XXXComponent, NgxTableResizerDirective],
})
export class xxx {}

kbsh avatar Sep 27 '21 13:09 kbsh

Adding a simple css rule for .datatable-scroll display: inherit !important; works for me

I used this way to avoid !important and also scope it to just the table(s) I needed to fix with .my-class.

.my-class .ngx-datatable .datatable-body .datatable-scroll {
  display: inherit;
}

emekaelo avatar Jan 19 '23 09:01 emekaelo

That's worked for me.. my package version: @swimlane/[email protected] As @manjeetyadv mention above I add css from this https://github.com/swimlane/ngx-datatable/issues/923#issuecomment-678753412

And also add this code:

@ViewChild('tableWrapper') tableWrapper;
  @ViewChild('dataListTable') dataListTable: DatatableComponent;
  private currentComponentWidth;
ngAfterViewChecked(): void {
    if (this.dataListTable && this.dataListTable.recalculate && (this.tableWrapper.nativeElement.clientWidth !== this.currentComponentWidth)) {
      this.currentComponentWidth = this.tableWrapper.nativeElement.clientWidth;
      this.dataListTable.recalculate();
      this._changeDetectorRef.detectChanges();
    }
  }

in html:

<div #tableWrapper>
        <!-- Table -->
        <ngx-datatable #dataListTable...

mustn avatar May 08 '23 09:05 mustn