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

ColumnWidthMode.auto is not working if i set autoExpandGroups: false, #2217

Closed
miraj98hossain opened this issue Dec 19, 2024 · 2 comments
Closed
Labels
data grid Data grid component waiting for customer response Cannot make further progress until the customer responds.

Comments

@miraj98hossain
Copy link

Bug description

I have added group feature in my sfdatagrid. So as per the documentation i have set

jobHisDataSource.addColumnGroup(
                      ColumnGroup(name: "Job Order No", sortGroupRows: false));

allowExpandCollapseGroup: true,
After that to stop auto expand group initially i have used
autoExpandGroups: false,
But when i use this property columnWidthMode: ColumnWidthMode.auto, don't work also when I use ColumnWidthMode.fitByCellValue it removes the whole datagrid.

Steps to reproduce

  1. Add these dependencies in your yaml file
syncfusion_flutter_datagrid: ^27.1.53
syncfusion_flutter_core: ^27.1.53`
  1. Run The below code.

Code sample

Code sample
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: 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,
      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),
                  ),
                ),
              ),
            )
      ],
    );
  }
}

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

Case 1:
When

autoExpandGroups: true,
columnWidthMode: ColumnWidthMode.auto,

Showing the full item name.

Screenshot_2
Case 2:
When

autoExpandGroups: false,
columnWidthMode: ColumnWidthMode.auto,

Item name is cropped

Screenshot_1
Case 3:
When

autoExpandGroups: false,
columnWidthMode: ColumnWidthMode.fitByCellValue,

Whole Table is not showing.

Screenshot_3

Stack Traces

Stack Traces
Built build\app\outputs\flutter-apk\app-debug.apk
Connecting to VM Service at ws://127.0.0.1:64045/yVDZv_1qks4=/ws
Connected to the VM Service.
I/mple.experiment(20342): Compiler allocated 5174KB to compile void android.view.ViewRootImpl.performTraversals()
Reloaded 1 of 755 libraries in 5,953ms (compile: 51 ms, reload: 1251 ms, reassemble: 3876 ms).
D/EGL_emulation(20342): app_time_stats: avg=14278.28ms min=1736.62ms max=26819.94ms count=2
Reloaded 1 of 755 libraries in 2,969ms (compile: 65 ms, reload: 997 ms, reassemble: 1703 ms).
D/EGL_emulation(20342): app_time_stats: avg=19974.65ms min=19974.65ms max=19974.65ms count=1
D/EGL_emulation(20342): app_time_stats: avg=5207.74ms min=5207.74ms max=5207.74ms count=1
D/EGL_emulation(20342): app_time_stats: avg=13227.06ms min=143.70ms max=26310.41ms count=2
D/EGL_emulation(20342): app_time_stats: avg=86.62ms min=30.31ms max=269.84ms count=12
2
D/ActivityThread(20342): Package [com.android.vending] reported as REPLACED, but missing application info. Assuming REMOVED.
Reloaded 1 of 755 libraries in 6,400ms (compile: 39 ms, reload: 1052 ms, reassemble: 5115 ms).
D/EGL_emulation(20342): app_time_stats: avg=1315.84ms min=26.04ms max=18845.60ms count=15
Reloaded 1 of 755 libraries in 12,622ms (compile: 91 ms, reload: 5830 ms, reassemble: 6021 ms).
D/EGL_emulation(20342): app_time_stats: avg=51831.46ms min=51831.46ms max=51831.46ms count=1
D/EGL_emulation(20342): app_time_stats: avg=4397.88ms min=4397.88ms max=4397.88ms count=1
Reloaded 1 of 755 libraries in 3,903ms (compile: 37 ms, reload: 1508 ms, reassemble: 2175 ms).
D/EGL_emulation(20342): app_time_stats: avg=21410.96ms min=146.77ms max=42675.13ms count=2
D/EGL_emulation(20342): app_time_stats: avg=4632.69ms min=4632.69ms max=4632.69ms count=1
D/EGL_emulation(20342): app_time_stats: avg=794.18ms min=34.60ms max=1553.76ms count=2
D/EGL_emulation(20342): app_time_stats: avg=690.37ms min=40.20ms max=1340.54ms count=2
2
D/ActivityThread(20342): Package [com.google.android.googlequicksearchbox] reported as REPLACED, but missing application info. Assuming REMOVED.
Reloaded 1 of 755 libraries in 3,622ms (compile: 58 ms, reload: 1202 ms, reassemble: 2183 ms).
D/EGL_emulation(20342): app_time_stats: avg=214364.17ms min=109.98ms max=428618.34ms count=2
Reloaded 1 of 755 libraries in 2,650ms (compile: 41 ms, reload: 830 ms, reassemble: 1655 ms).
D/EGL_emulation(20342): app_time_stats: avg=369884.91ms min=369884.91ms max=369884.91ms count=1
Reloaded 1 of 755 libraries in 2,015ms (compile: 37 ms, reload: 816 ms, reassemble: 1034 ms).

On which target platforms have you observed this bug?

Android

Flutter Doctor output

Doctor output
[√] 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.0)
    • 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 is enabled with autoExpandGroups set to false, all the DataGridRows are hidden, and only the caption summary rows are visible in the UI. For calculations like auto and fitByCellValue, we only involve the DataGridRows that are available in the UI, as determined by ColumnWidthCalculationRange.visibleRows. Therefore, this is the expected behavior on our end.

To avoid improper UI appearance and calculation issues, you can enable ColumnWidthCalculationRange.allRows. By default, the autofit calculation is performed only on visible rows. However, by setting the SfDataGrid.columnWidthCalculationRange property to ColumnWidthCalculationRange.allRows, the autofit calculation will be performed for all rows, ensuring that all rows in the DataGridRows are involved in the calculation and displayed correctly in the UI.

Please note that when ColumnWidthCalculationRange.allRows is enabled, all rows are included in the ColumnWidthMode calculation, which may affect the performance of the DataGrid.

We have provided a code snippets for your reference. Please refer to the attached code snippet for more details.

@override
  Widget build(BuildContext context) {
    return SfDataGrid(
      rowHeight: 32,
      headerRowHeight: 38,
      source: source,
      allowExpandCollapseGroup: true,
      columnWidthCalculationRange: ColumnWidthCalculationRange.allRows,
      autoExpandGroups: false,
      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),
                  ),
                ),
              ),
            )
      ],
    );
  }

Regards,
Abinesh P

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

Hi @miraj98hossain

In SfDataGrid, when grouping is enabled with autoExpandGroups set to false, all the DataGridRows are hidden, and only the caption summary rows are visible in the UI. For calculations like auto and fitByCellValue, we only involve the DataGridRows that are available in the UI, as determined by ColumnWidthCalculationRange.visibleRows. Therefore, this is the expected behavior on our end.

To avoid improper UI appearance and calculation issues, you can enable ColumnWidthCalculationRange.allRows. By default, the autofit calculation is performed only on visible rows. However, by setting the SfDataGrid.columnWidthCalculationRange property to ColumnWidthCalculationRange.allRows, the autofit calculation will be performed for all rows, ensuring that all rows in the DataGridRows are involved in the calculation and displayed correctly in the UI.

Please note that when ColumnWidthCalculationRange.allRows is enabled, all rows are included in the ColumnWidthMode calculation, which may affect the performance of the DataGrid.

We have provided a code snippets for your reference. Please refer to the attached code snippet for more details.

@override
  Widget build(BuildContext context) {
    return SfDataGrid(
      rowHeight: 32,
      headerRowHeight: 38,
      source: source,
      allowExpandCollapseGroup: true,
      columnWidthCalculationRange: ColumnWidthCalculationRange.allRows,
      autoExpandGroups: false,
      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),
                  ),
                ),
              ),
            )
      ],
    );
  }

Regards, Abinesh P

Good to know about that and thanks for clearing the concept.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
data grid Data grid component waiting for customer response Cannot make further progress until the customer responds.
Projects
None yet
Development

No branches or pull requests

3 participants