Angular:订阅 Observable 时,AgGrid 不会更新行 [英] Angular: AgGrid will not update rows when subscribing to Observable

查看:21
本文介绍了Angular:订阅 Observable 时,AgGrid 不会更新行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将 rxjs 和 observables 合并到 ag 网格中.为了练习,我正在关注一个官方的 ag 网格示例:https://www.ag-grid.com/javascript-grid-rxjs/

我目前使用的是 Angular 6.我将 js 文件更改为 ts 文件并进行了适当的更改.我的索引文件中也不包含任何脚本.每次调用脚本时,我都会收到一堆 MIME 错误.所以我将代码转换为严格的角度.我相信这是导致我的问题的原因.我的目标是让随机行改变它们​​的值,而不必在我订阅我的可观察更新时刷新网页

在下面的代码中,您将看到基本上是一个选择要显示的随机数的区间函数.当我运行我的代码时,所有数据都加载到我的网格中,但它不会刷新或更新.我订阅了updates$ observable 来输出更新的数据,但没有任何反应.这是代码.onGridReady 函数正在订阅 observable.

组件.ts

import { Component, OnInit } from '@angular/core';从../app/model"导入{Model};从 'rxjs' 导入 {Observable};从'@angular/common/http' 导入 { HttpClient };从'../app/mockServer' 导入 {MockServer}@零件({选择器:'app-root',模板:`<ag-grid-angular#agGrid样式=宽度:1000px;高度:1500px;"id="myGrid"[rowData]=rowData"class =ag-theme-balham"[columnDefs]=columnDefs"[enableRangeSelection]=真";[enableColResize]=真";[deltaRowDataMode]=真"[getRowNodeId]=getRowNodeId"(gridReady)="onGridReady($event)";></ag-grid-angular>,styleUrls: ['./app.component.css']})导出类 AppComponent 实现 OnInit{私有 gridApi;私有 gridColumnApi;私人行数据:任何[];私有列定义;私有 getRowNodeId;构造函数(){this.columnDefs = [{标题名称:代码",字段:代码",宽度:70},{标题名称:名称",字段:名称",宽度:300},{headerName: "投标",字段:投标",宽度:100,cellClass:细胞编号",valueFormatter: numberFormatter,cellRenderer:agAnimateShowChangeCellRenderer"},{标题名称:中",字段:中",宽度:100,cellClass:细胞编号",valueFormatter: numberFormatter,cellRenderer:agAnimateShowChangeCellRenderer"},{标题名称:询问",字段:询问",宽度:100,cellClass:细胞编号",valueFormatter: numberFormatter,cellRenderer:agAnimateShowChangeCellRenderer"},{标题名称:卷",字段:体积",宽度:80,cellClass:细胞编号",cellRenderer:agAnimateSlideCellRenderer"}];this.getRowNodeId = 数据 =>数据代码;}ngOnInit() {}onGridReady(参数){this.gridApi = params.api;this.gridColumnApi = params.columnApi;让 mockServer = new MockServer();const initialLoad$ = mockServer.initialLoad();const updates$ = mockServer.allDataUpdates();initialLoad$.subscribe(rowData => {params.api.setRowData(rowData);更新$.subscribe(newRowData => params.api.setRowData(newRowData));});}}函数 numberFormatter(params) {如果(typeof params.value ===数字"){返回 params.value.toFixed(2);} 别的 {返回参数值;}}

这里是服务器类.这包含操作数据的函数.为简洁起见,我只包括无法正常工作的方法.byRowupdates 无法正常工作

byRowupdates() {返回 Observable.create((观察者) => {const 间隔 = setInterval(() => {让变化 = [];//对数据进行一些模拟更改this.makeSomePriceChanges(changes);this.makeSomeVolumeChanges(changes);//观察者.next(变化);}, 1000);返回 () =>清除间隔(间隔);});}//为某些行提供随机数据更新//只有所有的行数据(一些行改变了)所有数据更新(){返回 Observable.create((观察者) => {const 间隔 = setInterval(() => {让变化 = [];//对数据进行一些模拟更改this.makeSomePriceChanges(changes);this.makeSomeVolumeChanges(changes);//这次我们只关心 delta 的变化//这次我们返回已更改其中行的完整数据集//observer.next(_.cloneDeep(this.rowData));}, 1000);返回 () =>清除间隔(间隔);});}/** 其余代码用于创建或修改模拟数据* 理解示例的其余部分并不重要(即其中的 rxjs 部分)*/回填数据(行数据){//样本数据只有名称和代码,我们需要添加虚拟数字rowData.forEach((dataItem) => {//使音量在 100 到 10,000 之间随机dataItem.volume = Math.floor((Math.random() * 10000) + 100);//中间随机从 20 到 300dataItem.mid = (Math.random() * 300) + 20;this.setBidAndAsk(dataItem);});返回行数据;}makeSomeVolumeChanges(更改){for (让 i = 0; i <10; i++) {//随机选取一个数据项const index = Math.floor(this.rowData.length * Math.random());const currentRowData = this.rowData[index];//改变 -5 到 5 之间的值const move = (Math.floor(10 * Math.random())) - 5;const newValue = currentRowData.volume + move;currentRowData.volume = newValue;变化.推(currentRowData);}}makeSomePriceChanges(更改){//随机更新某些行的数据for (让 i = 0; i <10; i++) {const index = Math.floor(this.rowData.length * Math.random());const currentRowData = this.rowData[index];//改变 -1 到 2 之间的值,保留一位小数const move = (Math.floor(30 * Math.random()))/10 - 1;const newValue = currentRowData.mid + 移动;currentRowData.mid = newValue;this.setBidAndAsk(currentRowData);变化.推(currentRowData);}}setBidAndAsk(数据项){dataItem.bid = dataItem.mid * 0.98;dataItem.ask = dataItem.mid * 1.02;}}

我的网格在创建时成功检索了数据,但网格没有更新新值.我的索引文件中没有任何脚本.这两个类正在做所有的工作.我对如何正确实现这个例子感到非常困惑.谢谢!

解决方案

您期望网格数据的数据绑定,但它不是那样工作的.要更新现有数据,您需要调用

rowNode.setData(data)

<块引用>

替换 rowNode 上的数据.完成后,网格将刷新整个渲染行(如果显示).

rowNode.setDataValue(colKey, value)

<块引用>

替换指定列的 rowNode 上的数据.完成后,网格将仅刷新所需行上的渲染单元格.

查看文档了解更多详情

*JFI 可以通过数据绑定进行更改,但您需要通过 node 进行更改并使用 node.data 进行操作,但我不建议使用这种类型的数据更新.

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!

解决方案

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.

这篇关于Angular:订阅 Observable 时,AgGrid 不会更新行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆