Closed TWY90 closed 8 months ago
Hi @TWY90 ,
The DataGrid will not recognize and refresh a particular cell by default whenever it changes. However, the DataGrid provides support for refreshing a specific cell based on its row and column indexes by using DataGridSource.notifyDataGridSourceListener
with the rowColumnIndex
property. You will need to determine the respective cell's row and column index and then manually call the notifyListener
method with these indexes. For more information on this topic, please refer to the following User Guide documentation. It explains how to bind and manipulate data with the SfDataGrid:
Data Manipulation in Flutter DataGrid - SfDataGrid
For your reference, we have implemented a DataGrid sample that dynamically change the cell values using a Timer. We hope it will help you clarify your doubts.
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'dart:async';
import 'dart:math';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Syncfusion DataGrid Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
MyHomePageState createState() => MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
late Timer timer;
late StockDataGridSource stockDataGridSource;
@override
void initState() {
super.initState();
stockDataGridSource = StockDataGridSource();
timer = Timer.periodic(const Duration(milliseconds: 200), (Timer args) {
stockDataGridSource.timerTick(args);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('SfDataGrid - Realtime update'),),
body: Card(
child: SfDataGrid(
source: stockDataGridSource,
columnWidthMode: ColumnWidthMode.none,
columns: <GridColumn>[
GridColumn(
columnName: 'stock',
label: Container(
alignment: Alignment.center,
child: const Text('Stock'),
),
),
GridColumn(
columnName: 'open',
label: Container(
alignment: Alignment.center,
child: const Text(' Open'),
),
),
GridColumn(
columnName: 'previousClose',
label: Container(
alignment: Alignment.center,
child: const Text('Previous Close'),
),
),
GridColumn(
columnName: 'lastTrade',
label: Container(
alignment: Alignment.center,
child: const Text('Last Trade'),
),
),
],
),
),
);
}
@override
void dispose() {
super.dispose();
timer.cancel();
}
}
class StockDataGridSource extends DataGridSource {
StockDataGridSource() {
_stocks = _getStocks(50);
buildDataGridRows();
}
final Random _random = Random();
List<Stock> _stocks = <Stock>[];
List<DataGridRow> _dataGridRows = <DataGridRow>[];
void timerTick(Timer args) {
refreshRows(100);
}
void refreshRows(int count) {
if (_stocks.length < count) {
count = _stocks.length;
}
for (int i = 0; i < count; ++i) {
final int recNo = _random.nextInt(_stocks.length);
// Reinitialize the DataGridRow for particular row and call the notify to
// view the realtime changes in DataGrid.
void updateDataRow() {
_dataGridRows[recNo] = DataGridRow(cells: <DataGridCell>[
DataGridCell<double>(
columnName: 'stock', value: _stocks[recNo].stock),
DataGridCell<double>(columnName: 'open', value: _stocks[recNo].open),
DataGridCell<double>(
columnName: 'previousClose', value: _stocks[recNo].previousClose),
DataGridCell<int>(
columnName: 'lastTrade', value: _stocks[recNo].lastTrade),
]);
}
_stocks[recNo].stock =
_stocksData[_random.nextInt(_stocksData.length - 1)];
updateDataRow();
updateDataSource(rowColumnIndex: RowColumnIndex(recNo, 0));
_stocks[recNo].open = 50.0 + _random.nextInt(40);
updateDataRow();
updateDataSource(rowColumnIndex: RowColumnIndex(recNo, 1));
updateDataRow();
_stocks[recNo].previousClose = 50.0 + _random.nextInt(30);
updateDataRow();
updateDataSource(rowColumnIndex: RowColumnIndex(recNo, 2));
_stocks[recNo].lastTrade = 50 + _random.nextInt(20);
updateDataRow();
updateDataSource(rowColumnIndex: RowColumnIndex(recNo, 3));
}
}
void buildDataGridRows() {
_dataGridRows = _stocks.map<DataGridRow>((Stock stock) {
return DataGridRow(cells: <DataGridCell>[
DataGridCell<double>(columnName: 'stock', value: stock.stock),
DataGridCell<double>(columnName: 'open', value: stock.open),
DataGridCell<double>(
columnName: 'previousClose', value: stock.previousClose),
DataGridCell<int>(columnName: 'lastTrade', value: stock.lastTrade),
]);
}).toList(growable: false);
}
@override
List<DataGridRow> get rows => _dataGridRows;
@override
DataGridRowAdapter buildRow(DataGridRow row) {
return DataGridRowAdapter(cells: <Widget>[
Container(
alignment: Alignment.center,
child: Text(row.getCells()[0].value.toString()),
),
Container(
alignment: Alignment.center,
child: Text(row.getCells()[1].value.toString()),
),
Container(
alignment: Alignment.center,
child: Text(row.getCells()[2].value.toString()),
),
Container(
alignment: Alignment.center,
child: Text(row.getCells()[3].value.toString()),
),
]);
}
void updateDataSource({required RowColumnIndex rowColumnIndex}) {
notifyDataSourceListeners(rowColumnIndex: rowColumnIndex);
}
// Data set for stock data collection
final List<double> _stocksData = <double>[
-0.76,
0.3,
0.42,
0.12,
0.55,
-0.78,
0.68,
0.99,
0.31,
-0.8,
-0.99,
0.43,
-0.5,
0.18,
-0.71,
-0.94
];
final List<String> _symbols = <String>[
'OJEC',
'PUYU',
'EXTB',
'QBLI',
'SFIO',
'MIXR',
'KQOW',
'DSHN',
'ZATR',
'SFBK',
'FLRT',
'PHKH',
];
List<Stock> _getStocks(int count) {
final List<Stock> stockData = <Stock>[];
for (int i = 1; i < _symbols.length; i++) {
stockData.add(Stock(
_symbols[i],
_stocksData[_random.nextInt(_stocksData.length - 1)],
50.0 + _random.nextInt(40),
50.0 + _random.nextInt(30),
50 + _random.nextInt(20)));
}
return stockData;
}
}
class Stock {
Stock(this.symbol, this.stock, this.open, this.previousClose, this.lastTrade);
String symbol;
double stock;
double open;
double previousClose;
int lastTrade;
}
Regards, Ashok K
Hi @TWY90 ,
The DataGrid will not recognize and refresh a particular cell by default whenever it changes. However, the DataGrid provides support for refreshing a specific cell based on its row and column indexes by using
DataGridSource.notifyDataGridSourceListener
with therowColumnIndex
property. You will need to determine the respective cell's row and column index and then manually call thenotifyListener
method with these indexes. For more information on this topic, please refer to the following User Guide documentation. It explains how to bind and manipulate data with the SfDataGrid:Data Manipulation in Flutter DataGrid - SfDataGrid
For your reference, we have implemented a DataGrid sample that dynamically change the cell values using a Timer. We hope it will help you clarify your doubts.
import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'dart:async'; import 'dart:math'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Syncfusion DataGrid Demo', theme: ThemeData(primarySwatch: Colors.blue), home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key}) : super(key: key); @override MyHomePageState createState() => MyHomePageState(); } class MyHomePageState extends State<MyHomePage> { late Timer timer; late StockDataGridSource stockDataGridSource; @override void initState() { super.initState(); stockDataGridSource = StockDataGridSource(); timer = Timer.periodic(const Duration(milliseconds: 200), (Timer args) { stockDataGridSource.timerTick(args); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('SfDataGrid - Realtime update'),), body: Card( child: SfDataGrid( source: stockDataGridSource, columnWidthMode: ColumnWidthMode.none, columns: <GridColumn>[ GridColumn( columnName: 'stock', label: Container( alignment: Alignment.center, child: const Text('Stock'), ), ), GridColumn( columnName: 'open', label: Container( alignment: Alignment.center, child: const Text(' Open'), ), ), GridColumn( columnName: 'previousClose', label: Container( alignment: Alignment.center, child: const Text('Previous Close'), ), ), GridColumn( columnName: 'lastTrade', label: Container( alignment: Alignment.center, child: const Text('Last Trade'), ), ), ], ), ), ); } @override void dispose() { super.dispose(); timer.cancel(); } } class StockDataGridSource extends DataGridSource { StockDataGridSource() { _stocks = _getStocks(50); buildDataGridRows(); } final Random _random = Random(); List<Stock> _stocks = <Stock>[]; List<DataGridRow> _dataGridRows = <DataGridRow>[]; void timerTick(Timer args) { refreshRows(100); } void refreshRows(int count) { if (_stocks.length < count) { count = _stocks.length; } for (int i = 0; i < count; ++i) { final int recNo = _random.nextInt(_stocks.length); // Reinitialize the DataGridRow for particular row and call the notify to // view the realtime changes in DataGrid. void updateDataRow() { _dataGridRows[recNo] = DataGridRow(cells: <DataGridCell>[ DataGridCell<double>( columnName: 'stock', value: _stocks[recNo].stock), DataGridCell<double>(columnName: 'open', value: _stocks[recNo].open), DataGridCell<double>( columnName: 'previousClose', value: _stocks[recNo].previousClose), DataGridCell<int>( columnName: 'lastTrade', value: _stocks[recNo].lastTrade), ]); } _stocks[recNo].stock = _stocksData[_random.nextInt(_stocksData.length - 1)]; updateDataRow(); updateDataSource(rowColumnIndex: RowColumnIndex(recNo, 0)); _stocks[recNo].open = 50.0 + _random.nextInt(40); updateDataRow(); updateDataSource(rowColumnIndex: RowColumnIndex(recNo, 1)); updateDataRow(); _stocks[recNo].previousClose = 50.0 + _random.nextInt(30); updateDataRow(); updateDataSource(rowColumnIndex: RowColumnIndex(recNo, 2)); _stocks[recNo].lastTrade = 50 + _random.nextInt(20); updateDataRow(); updateDataSource(rowColumnIndex: RowColumnIndex(recNo, 3)); } } void buildDataGridRows() { _dataGridRows = _stocks.map<DataGridRow>((Stock stock) { return DataGridRow(cells: <DataGridCell>[ DataGridCell<double>(columnName: 'stock', value: stock.stock), DataGridCell<double>(columnName: 'open', value: stock.open), DataGridCell<double>( columnName: 'previousClose', value: stock.previousClose), DataGridCell<int>(columnName: 'lastTrade', value: stock.lastTrade), ]); }).toList(growable: false); } @override List<DataGridRow> get rows => _dataGridRows; @override DataGridRowAdapter buildRow(DataGridRow row) { return DataGridRowAdapter(cells: <Widget>[ Container( alignment: Alignment.center, child: Text(row.getCells()[0].value.toString()), ), Container( alignment: Alignment.center, child: Text(row.getCells()[1].value.toString()), ), Container( alignment: Alignment.center, child: Text(row.getCells()[2].value.toString()), ), Container( alignment: Alignment.center, child: Text(row.getCells()[3].value.toString()), ), ]); } void updateDataSource({required RowColumnIndex rowColumnIndex}) { notifyDataSourceListeners(rowColumnIndex: rowColumnIndex); } // Data set for stock data collection final List<double> _stocksData = <double>[ -0.76, 0.3, 0.42, 0.12, 0.55, -0.78, 0.68, 0.99, 0.31, -0.8, -0.99, 0.43, -0.5, 0.18, -0.71, -0.94 ]; final List<String> _symbols = <String>[ 'OJEC', 'PUYU', 'EXTB', 'QBLI', 'SFIO', 'MIXR', 'KQOW', 'DSHN', 'ZATR', 'SFBK', 'FLRT', 'PHKH', ]; List<Stock> _getStocks(int count) { final List<Stock> stockData = <Stock>[]; for (int i = 1; i < _symbols.length; i++) { stockData.add(Stock( _symbols[i], _stocksData[_random.nextInt(_stocksData.length - 1)], 50.0 + _random.nextInt(40), 50.0 + _random.nextInt(30), 50 + _random.nextInt(20))); } return stockData; } } class Stock { Stock(this.symbol, this.stock, this.open, this.previousClose, this.lastTrade); String symbol; double stock; double open; double previousClose; int lastTrade; }
Regards, Ashok K
If you add SfDataPager realtime update doesn't work. I believe it's a bug
Hi @TWY90,
We are glad to inform you that the issue " The values in the DataGrid didn't refresh when calling notifyDataSourceListeners alongside DataPager" has been fixed and included in our weekly pub release. Please update the DataGrid package to version 24.1.43.
https://pub.dev/packages/syncfusion_flutter_datagrid
We suspect that the reported problem has been resolved in the DataGrid package version 24.1.43. We are closing this issue. Please let us know if you have any further queries on this. We are happy to help you.
Regards, Ashok K
Hi,
the website of sf say that datagrid has been optimized to handle high-frequency, real-time updates, and show the demo updating stock list in very fast speed. can sf provide the example code for the demo? for example how is the datagrid find the target stock ID/ index in table to update the specific row.
Thanks.