0
votes

I am trying to incorporate rxjs and observables into ag grid. For practice, I am following an official ag grid example: https://www.ag-grid.com/javascript-grid-rxjs/

I am currently using Angular 6. I changed the js file to be a ts file and made the appropriate changes. I also do not include any scripts in my index file. I was getting a bunch of MIME errors anytime I called a script. So I converted to code to strictly angular. I believe this is what is causing my issue. My goal is to have random rows change their values without having to refresh the web page when I subscribe to my updates observable

In the code below you will see there is basically an interval function that chooses random numbers to be displayed. When I run my code, All the data is loaded into my grid, but it does not refresh or update. I subscribe to the updates$ observable to output the updated data, but nothing happens. Here is the code. The onGridReady function is subscribing to the observable.

Component.ts

import { Component, OnInit } from '@angular/core';
import {Model} from '../app/model';
import {Observable} from 'rxjs';
import { HttpClient } from '@angular/common/http';
import {MockServer} from '../app/mockServer'

@Component({
    selector: 'app-root',
    template: 
    `<ag-grid-angular
    #agGrid
    style="width: 1000px; height: 1500px;"
    id="myGrid"
    [rowData]="rowData"
    class="ag-theme-balham"
    [columnDefs]="columnDefs"
    [enableRangeSelection]="true"
    [enableColResize]="true"
    [deltaRowDataMode]="true"
    [getRowNodeId]="getRowNodeId"
    (gridReady)="onGridReady($event)"
    ></ag-grid-angular>
` ,
   styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{

  private gridApi;
  private gridColumnApi;
  private rowData: any[];

  private columnDefs;
  private getRowNodeId;

    constructor() {
      this.columnDefs = [
        {
          headerName: "Code",
          field: "code",
          width: 70
        },
        {
          headerName: "Name",
          field: "name",
          width: 300
        },
        {
          headerName: "Bid",
          field: "bid",
          width: 100,
          cellClass: "cell-number",
          valueFormatter: numberFormatter,
          cellRenderer: "agAnimateShowChangeCellRenderer"
        },
        {
          headerName: "Mid",
          field: "mid",
          width: 100,
          cellClass: "cell-number",
          valueFormatter: numberFormatter,
          cellRenderer: "agAnimateShowChangeCellRenderer"
        },
        {
          headerName: "Ask",
          field: "ask",
          width: 100,
          cellClass: "cell-number",
          valueFormatter: numberFormatter,
          cellRenderer: "agAnimateShowChangeCellRenderer"
        },
        {
          headerName: "Volume",
          field: "volume",
          width: 80,
          cellClass: "cell-number",
          cellRenderer: "agAnimateSlideCellRenderer"
        }
      ];
      this.getRowNodeId = data => data.code;
    }

ngOnInit() {

}

onGridReady(params) {
  this.gridApi = params.api;
  this.gridColumnApi = params.columnApi;

  
  let mockServer = new MockServer();
  const initialLoad$ = mockServer.initialLoad();
  const updates$ = mockServer.allDataUpdates();
  initialLoad$.subscribe(rowData => {
    params.api.setRowData(rowData);
    updates$.subscribe(newRowData => params.api.setRowData(newRowData));

  });

}
 
}

function numberFormatter(params) {
  if (typeof params.value === "number") {
    return params.value.toFixed(2);
  } else {
    return params.value;
  }
}

Here is the server class. This contains the functions that manipulate the data. For brevity, I am only including the methods that are not working correctly. byRowupdates is what is not working properly

byRowupdates() {
        return Observable.create((observer) => {
            const interval = setInterval(() => {
                let changes = [];
                // make some mock changes to the data
                this.makeSomePriceChanges(changes);
                this.makeSomeVolumeChanges(changes);
               // observer.next(changes);
            }, 1000);
            return () => clearInterval(interval);
        });
    }
    // provides randomised data updates to some of the rows
    // only all the row data (with some rows changed)
    allDataUpdates() {
        return Observable.create((observer) => {
            const interval = setInterval(() => {
                let changes = [];
                // make some mock changes to the data
                this.makeSomePriceChanges(changes);
                this.makeSomeVolumeChanges(changes);
                // this time we don't care about the delta changes only
                // this time we return the full data set which has changed rows within it
                //observer.next(_.cloneDeep(this.rowData));
            }, 1000);

            return () => clearInterval(interval);
            
        });
    }
    /*
     * The rest of the code exists to create or modify mock data
     * it is not important to understand the rest of the example (i.e. the rxjs part of it)
     */
    backfillData(rowData) {
        // the sample data has just name and code, we need to add in dummy figures
        rowData.forEach((dataItem) => {
            // have volume a random between 100 and 10,000
            dataItem.volume = Math.floor((Math.random() * 10000) + 100);
            // have mid random from 20 to 300
            dataItem.mid = (Math.random() * 300) + 20;
            this.setBidAndAsk(dataItem);
        });
        return rowData;
    }
    makeSomeVolumeChanges(changes) {
        for (let i = 0; i < 10; i++) {
            // pick a data item at random
            const index = Math.floor(this.rowData.length * Math.random());
            const currentRowData = this.rowData[index];
            // change by a value between -5 and 5
            const move = (Math.floor(10 * Math.random())) - 5;
            const newValue = currentRowData.volume + move;
            currentRowData.volume = newValue;
            changes.push(currentRowData);
        }
    }
    makeSomePriceChanges(changes) {
        // randomly update data for some rows
        for (let i = 0; i < 10; i++) {
            const index = Math.floor(this.rowData.length * Math.random());
            const currentRowData = this.rowData[index];
            // change by a value between -1 and 2 with one decimal place
            const move = (Math.floor(30 * Math.random())) / 10 - 1;
            const newValue = currentRowData.mid + move;
            currentRowData.mid = newValue;
            this.setBidAndAsk(currentRowData);
            changes.push(currentRowData);
        }
    }
    setBidAndAsk(dataItem) {
        dataItem.bid = dataItem.mid * 0.98;
        dataItem.ask = dataItem.mid * 1.02;
    }
}

My grid is successfully retrieving the data when it is created, but the grid is not updating new values. I do not have any scripts in my index file. These two classes are doing all the work. I am very confused on how to implement this example properly. Thank you!

1

1 Answers

2
votes

You are expecting data-binding for grid-data, but it doesn't work like that. For updating existing data you need to call

rowNode.setData(data)

Replaces the data on the rowNode. When complete, the grid will refresh the the entire rendered row if it is showing.

or

rowNode.setDataValue(colKey, value)

Replaces the data on the rowNode for the specified column. When complete, the grid will refresh the rendered cell on the required row only.

Check doc for more details

*JFI changes through data-binding possible but you would require to make it via node and manipulate with node.data but I'm not recommending using this type of data-update.