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

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

Open webmatrixxxl opened 7 years ago

webmatrixxxl commented 7 years ago

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

katestearns-suplari commented 7 years ago

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

DavideRoss commented 7 years ago

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

insidewhy commented 6 years ago

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.

BBaysinger commented 6 years ago

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 commented 6 years ago

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.

ahmetacer5 commented 6 years ago

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

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

BBaysinger commented 6 years ago

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

ArfanMirza commented 6 years ago

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
                    }
                );
karljv commented 6 years ago

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>
GRTO commented 5 years ago

columnGroupWidths

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

karljv commented 5 years ago

I used the recalculate function on DatatableComponent

@ViewChild(DatatableComponent) datatable: DatatableComponent;

GevorgGabrielyan commented 5 years ago

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

appagg commented 5 years ago

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) { ... }

jrodg commented 5 years ago

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,

abierbaum commented 5 years ago

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)

leon99adolfo commented 4 years ago

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);
}
meenu1 commented 4 years ago

@ViewChild("table") table: DatatableComponent;

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

This works for me.

codingnut commented 4 years ago

@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!

UsmanMajied17 commented 4 years ago

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.

manjeetyadv commented 4 years ago

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; }

rishi1305 commented 3 years ago

@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

dp1127 commented 3 years ago

@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.

buiquanghungOU commented 3 years ago

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

this one work with me many thanks

kbsh commented 2 years ago

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 {}
emekaelo commented 1 year ago

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;
}
mustn commented 1 year ago

That's worked for me.. my package version: @swimlane/ngx-datatable@19.0.0 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...