3
votes

Normally I simply use the gridReady event, get the api and call sizeColumnsToFit().

export class MyGridApplicationComponent {
    private gridOptions: GridOptions;
    private showGrid2: false;

    constructor() {
        this.gridOptions = <GridOptions>{
          onGridReady: this.gridReady.bind(),
          ....
        };
    }
    gridReady(params) {
      params.api.sizeColumnsToFit();
    }
    ....

However, I have a grid that is in a hidden tab and so when the gridReady event is called, the width is 0 (get the message in the console: "tried to call sizeColumnsToFit() but the grid is coming back with zero width, maybe the grid is not visible yet on the screen?").

<h2>Grid only visible after button click</h2>
<button (click)="showGrid2 = true;">Show grid</button><br/><br/>
<div style="width: 100%;" [hidden]="!showGrid2">

    <ag-grid-angular #agGrid2 style="width: 100%; height: 200px;" class="ag-theme-fresh" [gridOptions]="gridOptions">
    </ag-grid-angular>
</div>

Is there an event I can hook into when the ag-grid becomes visible so I can resize/fit it? I've tried a few vaguely relevant events (gridSizeChanged, firstDataRendered, columnVisible, columnResized) to no avail.

I have a simplified repro in StackBlitz.

[EDIT] I tried a modification to @antirealm's suggestion below (seeing if *ngIf on the parent div made the difference) and this worked for my (over)simplified version of the problem: see StackBlitz repro.

This is all in context of a nested tabs component, where the ag-grid is not on the first tab. I've tried using *ngIf in the div containing the nested tab content:

<div *ngIf="hasBeenActive" [hidden]="!active"><ng-content></ng-content></div>

and even though the DOM shows that the ag-grid is not there, the ag-grid's gridReady event is still called before the second tab has been selected. See Stackblitz repro.

1
I've dealt with this problem before. My solution was to have an *ngIf on the grid component that becomes true when the tab is selected. In some cases you want the grid to stay there after it was created and not have to create each time, so you'd use something like *ngIf="tabSelected || tabHasBeenSelectedBefore". You'd have to set that second variable to true upon selecting the tab for the first time. - antirealm
Why you have the grid is in hidden tab? Is that the approach you are trying? Can you please elaborate what you are trying to achieve? - UI_Dev
@antirealm Yep, I used something similar, setting *ngIf to the parent div and that worked well. Unfortunately when I tried something similar in my tabs component, it did not. - monty
Here's a solution forked from yours stackblitz.com/edit/angular-ag-grid-angular-svdxuj - antirealm
certainly works! I was trying to avoid reference to one of the lower order ui elements but I think it's an even better solution that one I've found (wrapping the whole content in an ng-template and making my nested tabs use that, if it exists, in an ng-container: stackblitz.com/edit/angular-ag-grid-angular-u7hnx5) - monty

1 Answers

4
votes
  1. Solution to original over-simplified problem:
<div *ngIf="hasBeenShown" style="width: 100%;" [hidden]="!grid2Showing">  
  <ag-grid-angular #agGrid2 style="width: 100%; height: 200px;" class="ag-theme-fresh" [gridOptions]="gridOptions">
  </ag-grid-angular>
</div>
  1. Solutions to actual problem: ag-grid hitting gridReady when projected content (ng-content), in this case in a nested-tab component:

    a) (Solution from @antirealm) Make a publicly available 'hasBeenActive' variable on the nested-tab component, and then use it in an *ngIf direct on your ag-grid:

export class NestedTabComponent ... {
  ...
  public hasBeenActive: boolean = false;

  activate() {
    this.active = true;
    this.hasBeenActive = true; 
  }
  ....
<nested-tab title="Second grid" #myTab>
  <div style="width: 100%;">
    <ag-grid-angular *ngIf="myTab.hasBeenActive"
      ...>
    </ag-grid-angular>
  </div>    
</nested-tab>

     b) Modify the nested-tab component to use a template if one exists, then wrap the content of any nested-tab that shouldn't be initialised immediately in a template:

@Component({
    selector: 'nested-tab',
    template: `
    <div *ngIf="hasBeenActive" [hidden]="!active">
      <ng-container *ngTemplateOutlet="content"></ng-container>
      <ng-content></ng-content>
    </div>`
})
export class NestedTabComponent implements OnInit {
    @ContentChild(TemplateRef) content;
    ....
<nested-tab title="Second grid">
  <ng-template>
    <p>The Second grid rendered:</p>
    <div style="width: 100%;">      
      <ag-grid-angular ...></ag-grid-angular>
    </div>    
  </ng-template> 
</nested-tab>