简体   繁体   中英

AgGrid/Angular 2: No access to setRowData(). grid renders, no rowData is displayed

Solved (sort of) I believe my solution is jerry rigged and indicates that I set up my mongoose model improperly.

The answer below did help me solve my problem so I checked it, but in the end the reason for the blank data rows was incorrect identifiers in the property

ie. in my-gridcomponent-name.component.ts

gridOptions.columnDef.field 

I needed set the field property with the actual database field names/identifiers.

I was using the names/identifiers that I assigned in the mongoose Schema and not the database's actual field names/identifiers. For example, the Schema identifiers where all one word lower case while the database identifiers started with an uppercase and may have an _ between words.



Question starts here....


I am fetching an array of JSON objects from MongoDB and want to display them in agGrid.

$ng version angular-cli: 1.0.0-beta.28.3 node: 6.9.2 os: win32 x64 
@angular/common: 2.4.10 
@angular/compiler: 2.4.10 
@angular/core: 2.4.10 
@angular/forms: 2.4.10 
@angular/http: 2.4.10 
@angular/platform-browser: 2.4.10 
@angular/platform-browser-dynamic: 2.4.10 
@angular/router: 3.4.10 
@angular/compiler-cli: 2.4.10

I am 99% sure I have the data in array and it is available to my html page.

1) console.log(Array.isArray(self.catalogue)) //true

2) I tested *ngFor just below the <ag-grid-angular> tag. It worked.

<div *ngFor='let note of catalogue'> 
    <li>{{note.Country}}</li> 
    <li>{{note.Authority}}</li> ......etc 
</div>

This post has a screenshot of what my agGrid basically looks like -- it has headers and scroll bars as if the data was printed in invisible ink. UI Grid Angular, grid renders but doesn't display data

The rowData will display if I just hard code some objects in the constructor.

constructor(private catalogueService: CatalogueService) {
 this.gridOptions = <GridOptions>{},
 this.gridOptions.columnDefs = [
 {
  headerName: "Country",
  field: "country",
  width: 200
},.....
]    
this.gridOptions.rowData = [
  {country: 'pig', authority: 'A12', banknoteID: 'bn1', pickID: 'p1', currency: 'thalers', denomination: 10},   
  ]
}

Here is my .html file

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

my .ts file

import { Component, OnInit } from '@angular/core';
import { CatalogueService } from '../services/catalogue.service';
import { Catalogue } from '../models/Catalogue';
import { GridOptions } from 'ag-grid';

@Component({
  selector: 'app-ag-grid-catalogue',
  templateUrl: './ag-grid-catalogue.component.html',
  styleUrls: ['./ag-grid-catalogue.component.css']
})

export class AgGridCatalogueComponent implements OnInit {

private gridOptions: GridOptions;
private catalogue: Catalogue [];

constructor(private catalogueService: CatalogueService) {
   this.gridOptions = <GridOptions>{},
   this.gridOptions.columnDefs = [
    {
      headerName: "Country",
      field: "country",
      width: 200
    },....etc
  ]

   this.gridOptions.rowData = [ ]
  }
 //Methods
 loadCatalogue () {
   //Assign this to self to be used in callbacks
   var self = this;
     return this.catalogueService.getCatalogue().subscribe(function (data) {
        //Why can't I use dot notation to access the data param?
        //console.log(data) ==> {success: true, catalogue: Array(4)}
        if (data['success']) {
        //Bind "catalogue" to the [rowData] in the <ag-grid-angular> tag
        self.catalogue = data['catalogue']
        // tried and failed:self.gridOptions.rowData = data['catalogue'];          
        // return data['catalogue'];
       };
     })
    };

    ngOnInit () {
       this.loadCatalogue();
    };
   } 

Here is the service, but it appears that I am getting an array of JSON objects so I don't think the issue is in the service

import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';

import 'rxjs/add/operator/map';

@Injectable()
export class CatalogueService {

constructor(private http: Http) { }

private serverApi= 'http://localhost:3000';

public getCatalogue():Observable <Object> {
  // let headers = new Headers();
  // headers.append('Content-type', 'application/json');
  let URI = `${this.serverApi}` + `/`;
    return this.http.get(URI)
      .map(function (res) {
         return res.json();
      });
    }
  }

_______________________________________________________________________

====================== UPDATE per Dermo's advice ====================== _______________________________________________________________________

I still do not have access to a setRowData method.

After making your adjustments and adding a self. to one line of your code,

self.gridApi.setRowData(self.catalogue);

the console in the browser reads:

//error_handler.js:54 EXCEPTION: Cannot read property 'setRowData' of undefined

Swapping the above line of code for:

self.gridOptions.api.setRowData(self.catalogue)

ng serve compiles and there are no errors in the browser console, but... the row data is still not displayed.

Note, with a hard coded array in the this.gridOptions.rowData = [{blah, blah,...]} the grid renders that hard coded data but very quickly that data is erased and the grid is all empty rows.

It appears that neither my gridOptions object nor the gridApi object have a setRowData method on it. Should I see that method when clicking through the object shown in the browser console. I don't see any of the methods detailed in the api.docs you linked.

_______________________________________________________________________

Here are some more details (hopefully relevant.)

Before changing any code, I ran the program with a console.log inside the

loadCatalogue () {
//Assign this to self to be used in callbacks
var self = this;

return this.catalogueService.getCatalogue().subscribe(function (data) {
  if (data['success']) {        
      self.catalogue = data['catalogue']
      console.log('in cb', self)
    };
  })
};

console.log(self):
AgGridCatalogueComponent {catalogueService: CatalogueService, gridOptions: {…}, catalogue: Array(15)}
catalogue:        (15) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
catalogueService: CatalogueService {http: Http, serverApi: "http://localhost:3000"}
gridOptions:      { columnDefs: Array(11), 
                    rowData: Array(15), //(has the array of JSON objects I expected!)
                    api: GridApi,   //(with a list of properties/methods - as stated in the origainal question there is NO setRowData method)
                    columnApi: ColumnApi
                  }
__proto__:    Object

So, like you stated, the issue seems to be that the grid on the .html renders before the rowData property has been assigned a value.

Per your advice I added the 4 items to the program:

in .html

(gridReady)="onGridReady($event)"

in .ts

private gridApi;

gridApi.setRowData(self.catalogue);

onGridReady(params) {
  this.gridApi = params.api;
};

$ng serve does not compile: //Cannot find name 'gridApi' in the .ts

solution:

self.gridApi.setRowData(self.catalogue);  //Added the self. to the line of code

$ng serve now compiles, but...

console in the browser reads //error_handler.js:54 EXCEPTION: Cannot read property 'setRowData' of undefined

console.log(self):
Has one additional property: (due to the onGridReady(params) {this.gridApi = params.api;};????

gridApi:    GridApi {detailGridInfoMap: {…}, immutableService: ImmutableService, csvCreator: CsvCreator, excelCreator: null, gridCore: GridCore, …}

The problem is that ag-grid has been initialised with an empty array. You can solve this in many ways.

  • One option is to retrieve your catalogue data before loading your component.
  • Second option, detailed below, is to use the ag-grid api to set/update the
    grid data.

First of all, update your template to bind to the gridReady event

<div style="width: 1000px;">
  <ag-grid-angular #agGrid style="width: 100%; height: 200px;" 
    class="ag-fresh"
    [gridOptions]="gridOptions"
    [rowData]="catalogue"
    (gridReady)="onGridReady($event)">
  </ag-grid-angular>
</div>

Now add the onGridReady function to your .ts and add a reference to the grid api. Then set the data row in your loadCatalogue

import { Component, OnInit } from '@angular/core';
import { CatalogueService } from '../services/catalogue.service';
import { Catalogue } from '../models/Catalogue';
import { GridOptions } from 'ag-grid';

@Component({
  selector: 'app-ag-grid-catalogue',
  templateUrl: './ag-grid-catalogue.component.html',
  styleUrls: ['./ag-grid-catalogue.component.css']
})

export class AgGridCatalogueComponent implements OnInit {

private gridOptions: GridOptions;
private catalogue: Catalogue [];
private gridApi;

constructor(private catalogueService: CatalogueService) {
   this.gridOptions = <GridOptions>{},
   this.gridOptions.columnDefs = [
    {
      headerName: "Country",
      field: "country",
      width: 200
    },....etc
  ]

   this.gridOptions.rowData = [ ]
  }
 //Methods
 loadCatalogue () {
   //Assign this to self to be used in callbacks
   var self = this;
     return this.catalogueService.getCatalogue().subscribe(function (data) {
        //Why can't I use dot notation to access the data param?
        //console.log(data) ==> {success: true, catalogue: Array(4)}
        if (data['success']) {
        //Bind "catalogue" to the [rowData] in the <ag-grid-angular> tag
        self.catalogue = data['catalogue'];
        gridApi.setRowData(self.catalogue);
        // tried and failed:self.gridOptions.rowData = data['catalogue'];          
        // return data['catalogue'];
       };
     })
    };

    ngOnInit () {
       this.loadCatalogue();
    };

    onGridReady(params) {
      this.gridApi = params.api;
    };
   }

Updating grid data: https://www.ag-grid.com/javascript-grid-data-update/

Accessing api/data: https://www.ag-grid.com/javascript-grid-accessing-data/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM