Search code examples
javascriptangularag-gridag-grid-angular

Ag-Grid is not rendering data downloaded from server


I'm trying to use Ag-Grid for Angular to show datasets that I'm downloading from my back-end.
The component that it is supposed to show the table visualization is the following

dataset.component.html

<div class='body-container'>
    <ag-grid-angular 
        style="width: 1250px; height: 650px;" 
        class="ag-theme-balham"
        [enableFilter]="true"
        [pagination]="true"
        [rowData]="rowData" 
        [columnDefs]="columnDefs">
    </ag-grid-angular>
</div>

dataset.component.ts

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { DatasetService } from 'src/app/services/datasets.service';

@Component({
  selector: 'app-dataset',
  templateUrl: './dataset.component.html',
  styleUrls: ['./dataset.component.css']
})
export class DatasetComponent implements OnInit {

  columnDefs = [];

  rowData = [];

  datasetId;

  constructor(private router: ActivatedRoute,
              private datasetService: DatasetService) {
    debugger;
    this.router.queryParams.subscribe(async params => {
      this.datasetId = params['id'];
    });
   }

  async ngOnInit() {
    if (this.datasetId !== null || this.datasetId !== undefined) {
      await this.datasetService.showDataset(this.datasetId).toPromise().then((res) => {
        let dataset = JSON.parse(res['data']);
        const jsonKeys = Object.keys(dataset);
        jsonKeys.forEach((el) => {
          this.columnDefs.push(
            {
              headerName: el, 
              field: el
            });
        });
        const maxLength = Object.keys(dataset[jsonKeys[0]]).length;
        for (let i = 0; i < maxLength; i++) {
          let row = {}
          jsonKeys.forEach((el) => {
            row[el] = dataset[el][i];
          });
          this.rowData.push(row);
        }
        debugger;
      });
    }
  }

  

}

What I basically do is, since I don't know per-time how my columns and data are going to look like, to instantiate them on init of that component so that they can be passed to the ag-grid component. Sadly, this is not working.
I've also seen that the official guide is stating that, for fetching remote data, I should do

<div class='body-container'>
    <ag-grid-angular 
        style="width: 1250px; height: 650px;" 
        class="ag-theme-balham"
        [enableFilter]="true"
        [pagination]="true"
        [rowData]="rowData | async" 
        [columnDefs]="columnDefs">
    </ag-grid-angular>
</div>

but adding the async pipeline throws me this error

core.js:6014 ERROR Error: InvalidPipeArgument: '' for pipe 'AsyncPipe'
    at invalidPipeArgumentError (common.js:6367)
    at AsyncPipe._selectStrategy (common.js:7243)
    at AsyncPipe._subscribe (common.js:7224)
    at AsyncPipe.transform (common.js:7202)
    at Object.eval [as updateDirectives] (DatasetComponent.ngfactory.js:21)
    at Object.updateDirectives (core.js:44780)
    at checkAndUpdateView (core.js:44271)
    at callViewAction (core.js:44637)
    at execComponentViewsAction (core.js:44565)
    at checkAndUpdateView (core.js:44278)

Could anybody point me in the right direction?


Solution

  • Thankfully, found the answer... Essentially, Angular was rendering everything on random order, without helping me understanding very well what was happening.
    All I did was

    dataset.component.html

    <div class='body-container'>
        <ag-grid-angular 
            style="width: 1250px; height: 650px;" 
            class="ag-theme-balham"
            [enableFilter]="true"
            [pagination]="true"
            (gridReady)="onGridReady($event)"
        >
        </ag-grid-angular>
    </div>
    

    Removing the binding of the colDefs and rowData. Instead, when the grid is ready...

    dataset.component.ts

    import { Component, OnInit } from '@angular/core';
    import { Router, ActivatedRoute } from '@angular/router';
    import { DatasetService } from 'src/app/services/datasets.service';
    
    @Component({
      selector: 'app-dataset',
      templateUrl: './dataset.component.html',
      styleUrls: ['./dataset.component.css']
    })
    export class DatasetComponent implements OnInit {
    
      columnDefs = [];
    
      rowData = [];
    
      datasetId;
    
      
    
      constructor(private router: ActivatedRoute,
                  private datasetService: DatasetService) {
        debugger;
        this.router.queryParams.subscribe(async params => {
          this.datasetId = params['id'];
        });
       }
    
      async ngOnInit() {
     
      }
    
      async onGridReady(params) {
        await this.datasetService.showDataset(this.datasetId).toPromise().then((res) => {
          let dataset = JSON.parse(res['data']);
          const jsonKeys = Object.keys(dataset);
          jsonKeys.forEach((el) => {
            this.columnDefs.push(
              {
                headerName: el, 
                field: el
              });
          });
          const maxLength = Object.keys(dataset[jsonKeys[0]]).length;
          for (let i = 0; i < maxLength; i++) {
            let row = {}
            jsonKeys.forEach((el) => {
              row[el] = dataset[el][i];
            });
            this.rowData.push(row);
          }
          debugger;
        });
        params.api.setColumnDefs(this.columnDefs);
        params.api.setRowData(this.rowData);
      }
    
    }
    

    I just fetch the data from the server, force the function to wait for the download and then set the columns and the rowdata