Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable To Get Row Data When Datagrid Is Grouped. #2225

Closed
miraj98hossain opened this issue Dec 23, 2024 · 3 comments
Closed

Unable To Get Row Data When Datagrid Is Grouped. #2225

miraj98hossain opened this issue Dec 23, 2024 · 3 comments
Labels
data grid Data grid component feature New feature uncertain Uncertain feature

Comments

@miraj98hossain
Copy link

Bug description

I'm not receiving accurate row data when I try to retrieve it while the column is grouped. For instance, it gives me the second row data while I try to receive the first row data. The reason for this is that the data source's row list and the data grid list length don't match since the data grid contains extra group header rows.

How can I solve this ??

onCellTap: (details) {
        if (details.rowColumnIndex.columnIndex == 2) {
          log(source._jobHisRowData[details.rowColumnIndex.rowIndex - 1]
              .getCells()
              .elementAt(2)
              .value);
        }
      },

Steps to reproduce

  1. Import the package.
  2. Run the below code.

Code sample

Code sample
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: JobHistoryPage(),
    );
  }
}

class JobHistoryPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Dummy job history list
    List<JobHistory> dummyJobHistoryList = List.generate(
      20,
      (index) => JobHistory(
        jobOrderNo: "Job_$index",
        fpoNo: "FPO_$index",
        item: "ItemAbcdEfg_$index",
        creationDate: "2024-12-19",
        planStartDate: "2024-12-20",
        planCmplDate: "2024-12-25",
        fpoQty: index * 100,
        goodQty: index * 90,
        badQty: index * 10,
        trnQty: index * 80,
        rackQty: index * 70,
        madeP: (index % 100).toDouble(),
        dueMadeP: (100 - index % 100).toDouble(),
        customerName: "Customer_$index",
        customerPo: "PO_$index",
        buyerName: "Buyer_$index",
      ),
    );

    final jobHistoryDataSource = JobHistoryDataSource(
      jobHistoryData: dummyJobHistoryList,
    );
    jobHistoryDataSource.addColumnGroup(
        ColumnGroup(name: "Job Order No", sortGroupRows: false));

    return Scaffold(
      appBar: AppBar(
        title: const Text("Job History Table"),
      ),
      body: Center(
        child: SingleChildScrollView(
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: SizedBox(
              height: MediaQuery.of(context).size.height * 0.8,
              child: JobDetailsTableWidget(
                source: jobHistoryDataSource,
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class JobDetailsTableWidget extends StatelessWidget {
  const JobDetailsTableWidget({super.key, required this.source});

  final JobHistoryDataSource source;

  @override
  Widget build(BuildContext context) {
    return SfDataGrid(
      rowHeight: 32,
      headerRowHeight: 38,
      source: source,
      allowExpandCollapseGroup: true,
      // autoExpandGroups: false,
      columnWidthCalculationRange: ColumnWidthCalculationRange.allRows,
      frozenColumnsCount: 2,
      groupCaptionTitleFormat: '{Key} - {ItemsCount}',
      gridLinesVisibility: GridLinesVisibility.both,
      headerGridLinesVisibility: GridLinesVisibility.none,
      columnWidthMode: ColumnWidthMode.auto,
      shrinkWrapRows: true,
      columns: <GridColumn>[
        ...source.rows.first.getCells().map(
              (cell) => GridColumn(
                visible: !["Job Order No"].contains(cell.columnName),
                columnName: cell.columnName,
                label: Container(
                  alignment: Alignment.center,
                  child: Text(
                    cell.columnName,
                    style: const TextStyle(fontWeight: FontWeight.bold),
                  ),
                ),
              ),
            )
      ],
      onCellTap: (details) {
        if (details.rowColumnIndex.columnIndex == 2) {
          log(source._jobHisRowData[details.rowColumnIndex.rowIndex - 1]
              .getCells()
              .elementAt(2)
              .value);
        }
      },
    );
  }
}

class JobHistoryDataSource extends DataGridSource {
  /// Creates the employee data source class with required details.
  JobHistoryDataSource({required List<JobHistory> jobHistoryData}) {
    _jobHisData = jobHistoryData;
    _jobHisRowData = jobHistoryData.map<DataGridRow>((e) {
      Map<String, dynamic> map = e.toMapForTab();
      return DataGridRow(
        cells: [
          ...List.generate(
            map.length,
            (index) {
              return DataGridCell(
                columnName: map.entries.elementAt(index).key,
                value: map.entries.elementAt(index).value,
              );
            },
          )
        ],
      );
    }).toList();
  }

  List<DataGridRow> _jobHisRowData = [];
  List<JobHistory> _jobHisData = [];
  @override
  List<DataGridRow> get rows => _jobHisRowData;
  List<JobHistory> get jobHisData => _jobHisData;
  @override
  DataGridRowAdapter buildRow(DataGridRow row) {
    final int rowIndex = effectiveRows.indexOf(row);

    return DataGridRowAdapter(
        cells: row.getCells().map<Widget>((e) {
      LinearGradient? getColor() {
        if (e.columnName == 'Made P %') {
          try {
            Color fillColor = Colors.green;
            double fillPercent = double.parse(e.value
                .toString()
                .replaceAll('%', '')); // fills for container from side
            if (fillPercent <= 10) {
              fillColor = Colors.red; // 0-10
            } else if (fillPercent <= 20) {
              fillColor = Colors.deepOrange; // 10-20
            } else if (fillPercent <= 30) {
              fillColor = Colors.orange; // 20-30
            } else if (fillPercent <= 40) {
              fillColor = Colors.amber; // 30-40
            } else if (fillPercent <= 50) {
              fillColor = Colors.yellow; // 40-50
            } else if (fillPercent <= 60) {
              fillColor = Colors.teal; // 50-60
            } else if (fillPercent <= 70) {
              fillColor = Colors.cyan; // 60-70
            } else if (fillPercent <= 80) {
              fillColor = Colors.blue; // 70-80
            } else if (fillPercent <= 90) {
              fillColor = Colors.indigo; // 80-90
            } else if (fillPercent < 100) {
              fillColor = Colors.purple; // 90-99
            } else {
              fillColor = Colors.green; // 100
            }
            fillPercent = fillPercent / 100;
            // Return a gradient based on the value
            return LinearGradient(
              begin: Alignment.centerLeft,
              end: Alignment.centerRight,
              tileMode: TileMode.clamp,
              stops: [
                0.0,
                fillPercent,
                fillPercent,
                1.0
              ], // Adjust stops for smooth transition
              colors: [
                fillColor,
                fillColor,
                Colors.white,
                Colors.white,

                // Background color
              ],
            );
          } catch (e) {
            return null;
          }
        }
        return null; // Return null for non-relevant columns
      }

      TextStyle? getTextStyle() {
        return [
          "Made P %",
          "Job Order No",
        ].contains(e.columnName)
            ? const TextStyle(
                fontWeight: FontWeight.bold,
              )
            : null;
      }

      return Container(
        decoration: BoxDecoration(gradient: getColor()),
        alignment: [
          "FPO No",
          "FPO Qty",
          "Total Made Qty",
          "Good Qty",
          "Bad Qty",
          "Trn Qty",
          "Rack Qty",
          "Made P %",
          "Due Made P %"
        ].contains(e.columnName)
            ? Alignment.centerRight
            : Alignment.centerLeft,
        padding: const EdgeInsets.all(8.0),
        child: Text(
          e.value.toString(),
          textAlign: TextAlign.center,
          style: getTextStyle(),
        ),
      );
    }).toList());
  }

  @override
  Widget? buildGroupCaptionCellWidget(
      RowColumnIndex rowColumnIndex, String summaryValue) {
    return Container(
        padding: const EdgeInsets.symmetric(
          horizontal: 5,
          vertical: 5,
        ),
        child: Text(summaryValue));
  }
}

class JobHistory {
  final String? jobOrderNo;
  final String? fpoNo;
  final String? item;
  final String? creationDate;
  final String? planStartDate;
  final String? planCmplDate;
  final num? fpoQty;
  final num? goodQty;
  final num? badQty;
  final num? trnQty;
  final num? rackQty;
  final double? madeP;
  final double? dueMadeP;
  final String? customerName;
  final String? customerPo;
  final String? buyerName;

  JobHistory({
    this.jobOrderNo,
    this.fpoNo,
    this.item,
    this.creationDate,
    this.planStartDate,
    this.planCmplDate,
    this.fpoQty,
    this.goodQty,
    this.badQty,
    this.trnQty,
    this.rackQty,
    this.madeP,
    this.dueMadeP,
    this.customerName,
    this.customerPo,
    this.buyerName,
  });

  Map<String, dynamic> toMapForTab() {
    return {
      "Job Order No": jobOrderNo,
      "FPO No": fpoNo,
      "Item": item,
      "FPO Qty": fpoQty,
      "Good Qty": goodQty,
      "Bad Qty": badQty,
      "Trn Qty": trnQty,
      "Rack Qty": rackQty,
      "Made P %": "$madeP %",
      "Due Made P %": "$dueMadeP %",
    };
  }
}

Screenshots or Video

Screenshots / Video demonstration

Screenshot_4

Stack Traces

Stack Traces
Launching lib\main.dart on sdk gphone64 x86 64 in debug mode...
√ Built build\app\outputs\flutter-apk\app-debug.apk
Connecting to VM Service at ws://127.0.0.1:63260/VHruJfd1ubM=/ws
Connected to the VM Service.
[log] ItemAbcdEfg_1
D/EGL_emulation(18255): app_time_stats: avg=4385.77ms min=236.39ms max=8535.15ms count=2

On which target platforms have you observed this bug?

Android, iOS

Flutter Doctor output

Doctor output
PS D:\development\flutter_projects\experiment> flutter doctor -v
[√] Flutter (Channel stable, 3.24.3, on Microsoft Windows [Version 10.0.19045.5247], locale
    en-US)
    • Flutter version 3.24.3 on channel stable at C:\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 2663184aa7 (3 months ago), 2024-09-11 16:27:48 -0500
    • Engine revision 36335019a8
    • Dart version 3.5.3
    • DevTools version 2.37.3

[√] Windows Version (Installed version of Windows is version 10 or higher)

[√] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
    • Android SDK at C:\Users\miraj\AppData\Local\Android\sdk
    • Platform android-35, build-tools 35.0.0
    • Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java      
    • Java version OpenJDK Runtime Environment (build 21.0.3+-12282718-b509.11) 
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[X] Visual Studio - develop Windows apps
    X Visual Studio not installed; this is necessary to develop Windows apps.
      Download at https://visualstudio.microsoft.com/downloads/.
      Please install the "Desktop development with C++" workload, including all of its default      components

[√] Android Studio (version 2024.2)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.3+-12282718-b509.11)

[√] VS Code (version 1.96.2)
    • VS Code at C:\Users\miraj\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.102.0

[√] Connected device (4 available)
    • sdk gphone64 x86 64 (mobile) • emulator-5554 • android-x64    • Android 15 (API 35)     
      (emulator)
    • Windows (desktop)            • windows       • windows-x64    • Microsoft Windows       
      [Version 10.0.19045.5247]
    • Chrome (web)                 • chrome        • web-javascript • Google Chrome
      131.0.6778.86
    • Edge (web)                   • edge          • web-javascript • Microsoft Edge
      130.0.2849.80

[√] Network resources
    • All expected network resources are available.

! Doctor found issues in 1 category.
@abineshPalanisamy
Copy link

Hi @miraj98hossain ,

In SfDataGrid, when grouping support is enabled, the grouped rows collection is maintained internally. In the effective rows collection, only visible DataGridRows are included. The DataGridSource.rows property contains only the total rows without the grouped rows, which means it does not account for the grouping hierarchy. Consequently, it is not possible to fetch the correct row using the rowIndex when grouping is applied.

Currently, the DataGrid does not support obtaining a row using the RowColumnIndex from the onCellTap callback when grouping is applied. However, We have already considered your request as a feature. We will implement this feature in any of our upcoming releases. At the planning stage for every release cycle, we review all open features and identify features for implementation based on specific parameters including product vision, technological feasibility, and customer interest.

We appreciate your patience and understanding in the meantime. For further updates, you can refer to the feedback provided below.

Feedback - 50282

Regards,
Abinesh P

@miraj98hossain
Copy link
Author

Hi @miraj98hossain ,

In SfDataGrid, when grouping support is enabled, the grouped rows collection is maintained internally. In the effective rows collection, only visible DataGridRows are included. The DataGridSource.rows property contains only the total rows without the grouped rows, which means it does not account for the grouping hierarchy. Consequently, it is not possible to fetch the correct row using the rowIndex when grouping is applied.

Currently, the DataGrid does not support obtaining a row using the RowColumnIndex from the onCellTap callback when grouping is applied. However, We have already considered your request as a feature. We will implement this feature in any of our upcoming releases. At the planning stage for every release cycle, we review all open features and identify features for implementation based on specific parameters including product vision, technological feasibility, and customer interest.

We appreciate your patience and understanding in the meantime. For further updates, you can refer to the feedback provided below.

Feedback - 50282

Regards, Abinesh P

Okay! Please Consider it as a much need feature

@ashok-kuvaraja ashok-kuvaraja added data grid Data grid component waiting for customer response Cannot make further progress until the customer responds. labels Dec 23, 2024
@ashok-kuvaraja
Copy link
Collaborator

Hi @miraj98hossain,

We are closing this issue now. You can follow the feedback link for further updates. If you need any further assistance, please reopen this. We are always happy to help.

Regards,
Ashok K

@ashok-kuvaraja ashok-kuvaraja added uncertain Uncertain feature feature New feature and removed waiting for customer response Cannot make further progress until the customer responds. labels Dec 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
data grid Data grid component feature New feature uncertain Uncertain feature
Projects
None yet
Development

No branches or pull requests

3 participants