Skip to content

[syncfusion_flutter_datagrid]: onQueryRowHeight doesn't correctly adjust the height of the row depend on the content. #2248

Open
@wartelski

Description

@wartelski

Bug description

I need to change the height of the row in case if the content inside of the cell gets bigger.
Screenshot 2025-01-07 at 4 41 36 PM

I found that the best solution for this is to use onQueryRowHeight. But, for some reason, it doesn't work as expected.

Here is an example

  • when there is not enough space in the cell, the second button goes under the first button. That's expected behavior, and onQueryRowHeight does the correct job here.
 GridColumn(
            columnName: 'button',
            width: 100,
            label: Container(
              padding: const EdgeInsets.all(8.0),
              alignment: Alignment.center,
              child: const Text('Details'),
            ),
          ),
Screenshot 2025-01-07 at 4 34 02 PM
  • when there is enough space in the cell and two buttons in the row, then for some reason the height is still the same as if the two buttons were under each other. onQueryRowHeight does NOT work properly in this case. Why is there so much height applied?
 GridColumn(
            columnName: 'button',
            width: 300,
            label: Container(
              padding: const EdgeInsets.all(8.0),
              alignment: Alignment.center,
              child: const Text('Details'),
            ),
          ),
Screenshot 2025-01-07 at 4 36 49 PM

without using onQueryRowHeight:
Screenshot 2025-01-07 at 4 41 01 PM

My expectation is:

  • when there is enough space in the cell, it should look like this::
Screenshot 2025-01-07 at 4 41 01 PM
  • when there is not enough space in the cell, it should look like this:
Screenshot 2025-01-07 at 4 34 02 PM

Thank you.

Steps to reproduce

  1. apply onQueryRowHeight
  2. add two buttons in the cell
  3. make the width of the cell big enough, so the button will follow each other.

Code sample

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

void main() {
  runApp(MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const SfDataGridDemo()));
}

class SfDataGridDemo extends StatefulWidget {
  const SfDataGridDemo({Key? key}) : super(key: key);

  @override
  _SfDataGridDemoState createState() => _SfDataGridDemoState();
}

class _SfDataGridDemoState extends State<SfDataGridDemo> {
  List<Employee> _employees = <Employee>[];
  late EmployeeDataSource _employeeDataSource;

  @override
  void initState() {
    super.initState();
    _employees = getEmployeeData();
    _employeeDataSource = EmployeeDataSource(_employees);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter SfDataGrid'),
      ),
      body: SfDataGrid(
        source: _employeeDataSource,
        onQueryRowHeight: (details) {
          return details.getIntrinsicRowHeight(details.rowIndex);
        },
        columnWidthMode: ColumnWidthMode.fill,
        columns: [
          GridColumn(
            columnName: 'id',
            width: 50,
            label: Container(
              padding: const EdgeInsets.all(8.0),
              alignment: Alignment.center,
              child: const Text('ID'),
            ),
          ),
          GridColumn(
            columnName: 'name',
            width: 50,
            label: Container(
              padding: const EdgeInsets.all(8.0),
              alignment: Alignment.center,
              child: const Text('Name'),
            ),
          ),
          GridColumn(
            columnName: 'designation',
            width: 50,
            label: Container(
              padding: const EdgeInsets.all(8.0),
              alignment: Alignment.center,
              child: const Text('Designation'),
            ),
          ),
          GridColumn(
            columnName: 'button',
            width: 220,
            label: Container(
              padding: const EdgeInsets.all(8.0),
              alignment: Alignment.center,
              child: const Text('Details'),
            ),
          ),
        ],
      ),
    );
  }

  List<Employee> getEmployeeData() {
    return [
      Employee(10001, 'James', 'Project Lead '),
      Employee(10002, 'Kathryn', 'Manager'),
      Employee(10003, 'Lara', 'Developer'),
      Employee(10004, 'Michael', 'Designer'),
      Employee(10005, 'Martin', 'Developer'),
      Employee(10006, 'Newberry', 'Developer'),
      Employee(10007, 'Balnc', 'Developer'),
      Employee(10008, 'Perry', 'Developer'),
      Employee(10009, 'Gable', 'Developer'),
      Employee(10010, 'Grimes', 'Developer'),
    ];
  }
}

class EmployeeDataSource extends DataGridSource {
  EmployeeDataSource(List<Employee> employees) {
    buildDataGridRow(employees);
  }

  void buildDataGridRow(List<Employee> employeeData) {
    dataGridRow = employeeData.map<DataGridRow>((employee) {
      return DataGridRow(cells: [
        DataGridCell<int>(columnName: 'id', value: employee.id),
        DataGridCell<String>(columnName: 'name', value: employee.name),
        DataGridCell<String>(
            columnName: 'designation', value: employee.designation),
        const DataGridCell<Widget>(columnName: 'button', value: null),
      ]);
    }).toList();
  }

  List<DataGridRow> dataGridRow = <DataGridRow>[];

  @override
  List<DataGridRow> get rows => dataGridRow.isEmpty ? [] : dataGridRow;

  @override
  DataGridRowAdapter? buildRow(DataGridRow row) {
    return DataGridRowAdapter(
      cells: row.getCells().map<Widget>((dataGridCell) {
        return Container(
          alignment: Alignment.center,
          child: dataGridCell.columnName == 'button'
              ? LayoutBuilder(
                  builder: (BuildContext context, BoxConstraints constraints) {
                    return Wrap(
                      spacing: 4.0,
                      runSpacing: 4.0,
                      children: [
                        ElevatedButton(
                          onPressed: () {
                            showDialog(
                              context: context,
                              builder: (context) => AlertDialog(
                                content: SizedBox(
                                  height: 100,
                                  child: Column(
                                    mainAxisAlignment:
                                        MainAxisAlignment.spaceBetween,
                                    children: [
                                      Text(
                                          'Employee ID: ${row.getCells()[0].value.toString()}'),
                                      Text(
                                          'Employee Name: ${row.getCells()[1].value.toString()}'),
                                      Text(
                                          'Employee Designation: ${row.getCells()[2].value.toString()}'),
                                    ],
                                  ),
                                ),
                              ),
                            );
                          },
                          child: const Text('Details'),
                        ),
                        ElevatedButton(
                          onPressed: () {
                            showDialog(
                              context: context,
                              builder: (context) => AlertDialog(
                                content: SizedBox(
                                  height: 100,
                                  child: Column(
                                    mainAxisAlignment:
                                        MainAxisAlignment.spaceBetween,
                                    children: [
                                      Text(
                                          'Employee ID: ${row.getCells()[0].value.toString()}'),
                                      Text(
                                          'Employee Name: ${row.getCells()[1].value.toString()}'),
                                      Text(
                                          'Employee Designation: ${row.getCells()[2].value.toString()}'),
                                    ],
                                  ),
                                ),
                              ),
                            );
                          },
                          child: const Text('Details'),
                        ),
                      ],
                    );
                  },
                )
              : Text(
                  dataGridCell.value.toString(),
                  overflow: TextOverflow.ellipsis,
                ),
        );
      }).toList(),
    );
  }
}

class Employee {
  Employee(this.id, this.name, this.designation);
  final int id;
  final String name;
  final String designation;
}

Screenshots or Video

Screenshots / Video demonstration Screenshot 2025-01-07 at 4 52 37 PM

Stack Traces

Stack Traces
[Add the Stack Traces here]

On which target platforms have you observed this bug?

Web

Flutter Doctor output

Doctor output
   [✓] Flutter (Channel stable, 3.27.1, on macOS 15.0 ... darwin-arm64, locale en-US)
    • Flutter version 3.27.1 on channel stable at /...
    • Upstream repository ...
    • Framework revision ...
    • Engine revision ...
    • Dart version 3.6.0
    • DevTools version 2.40.2
    
    [✓] Xcode - develop for iOS and macOS (Xcode 16.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build ...
    • CocoaPods version 1.13.0
    
    [✓] IntelliJ IDEA Ultimate Edition (version 2024.1.4)
    • IntelliJ at /Applications/IntelliJ IDEA.app
    • Flutter plugin version 81.0.2
    • Dart plugin version 241.18808


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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions