Search code examples
flutterdartdatatablessyncfusionsyncfusion-chart

Flutter: SfDataGrid auto width columns doesn't seem to work as per documentation


Having followed the examples here and thoroughly read the documentation here, I simply don't understand why my columns don't show all their content.

See in this screenshot, but the email and phone number columns are cut off: Screenshot 2022-07-20 at 10 42 11

Things I tried to pay attention to:

  • Making sure the padding matched on the column and cell builders
  • Removing any fixed widths
  • Disabling softWrap everywhere I could

Any help to explain why this is happening would be greatly appreciated, thanks.

Page:

import 'package:flutter/material.dart';
import 'package:gt_elite/datasource/athlete_data_source.dart';
import 'package:gt_elite/helpers/colors.dart';
import 'package:gt_elite/helpers/constants.dart';
import 'package:gt_elite/helpers/gt_text_style.dart';
import 'package:gt_elite/models/team.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:easy_localization/easy_localization.dart';

class ManagementAdminScreen extends StatelessWidget {
  final Team team;

  ManagementAdminScreen({@required this.team});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
          color: Colors.white,
          child: SfDataGrid(
            source: AthleteDataSource(
              athletes: team.getAthletesForProfile(Profile.athlete),
            ),
            columnWidthMode: ColumnWidthMode.auto,
            columnWidthCalculationRange: ColumnWidthCalculationRange.allRows,
            frozenColumnsCount: 0,
            columns: [
              _buildColumn('avatar', 'profile.athlete'),
              _buildColumn('email', 'email'),
              _buildColumn('phoneNumber', 'phoneNumber'),
              _buildColumn('birthdate', 'birthdate'),
              _buildColumn('height', 'height'),
            ],
          )),
    );
  }

  GridColumn _buildColumn(String name, String lbl) {
    return GridColumn(
      autoFitPadding: EdgeInsets.symmetric(horizontal: 16.0),
      columnName: name,
      label: Container(
        padding: EdgeInsets.symmetric(horizontal: 16.0),
        alignment: Alignment.centerLeft,
        child: Text(
          lbl.tr(),
          style: GTTextStyle.subtitle2.copyWith(
            color: GTColors.textGrey,
          ),
          softWrap: false,
        ),
      ),
    );
  }
}

AthleteDataSource

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:gt_elite/helpers/gt_text_style.dart';
import 'package:gt_elite/helpers/string.dart';
import 'package:gt_elite/models/athlete.dart';
import 'package:intl/intl.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:url_launcher/url_launcher.dart';

class AthleteDataSource extends DataGridSource {
  final _dateFormatter = DateFormat.yMd();

  AthleteDataSource({List<Athlete> athletes}) {
    dataGridRows = athletes
        .map<DataGridRow>(
          (dataGridRow) => DataGridRow(
            cells: [
              DataGridCell<Athlete>(
                columnName: 'avatar',
                value: dataGridRow,
              ),
              DataGridCell<String>(
                columnName: 'email',
                value: dataGridRow.email,
              ),
              DataGridCell<String>(
                columnName: 'phone',
                value: dataGridRow.phoneNumber,
              ),
              DataGridCell<DateTime>(
                columnName: 'birthdate',
                value: dataGridRow.birthdate,
              ),
              DataGridCell<double>(
                columnName: 'height',
                value: dataGridRow.height,
              ),
            ],
          ),
        )
        .toList();
  }

  List<DataGridRow> dataGridRows = [];

  @override
  List<DataGridRow> get rows => dataGridRows;

  @override
  bool shouldRecalculateColumnWidths() {
    return true;
  }

  void _launchCaller(String url) async {
    final uri = Uri.parse(url);
    if (await canLaunchUrl(uri)) {
      await launchUrl(uri);
    } else {
      throw 'Could not launch $uri';
    }
  }

  @override
  DataGridRowAdapter buildRow(DataGridRow row) {
    return DataGridRowAdapter(
        cells: row.getCells().map<Widget>((dataGridCell) {
      // Avatar cell
      if (dataGridCell.columnName == 'avatar') {
        if (dataGridCell.value.getAvatarUrl() != null) {
          return Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                SizedBox(
                  width: 18,
                ),
                if (dataGridCell.value.getAvatarUrl() != null)
                  Padding(
                    padding: const EdgeInsets.only(right: 8.0),
                    child: Container(
                      width: 30,
                      height: 30,
                      // decoration: getBoxDecoration(),
                      child: ClipOval(
                        child: CachedNetworkImage(
                          height: 30,
                          width: 30,
                          imageUrl: dataGridCell.value.getAvatarUrl(),
                          placeholder: (context, url) =>
                              CircularProgressIndicator(),
                          errorWidget: (context, url, error) =>
                              Icon(Icons.error),
                        ),
                      ),
                    ),
                  ),
                if (dataGridCell.value.getAvatarUrl() == null)
                  SizedBox(
                    width: 30,
                  ),
                Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    FittedBox(
                      fit: BoxFit.scaleDown,
                      child: Text(
                        "${StringHelper.shortName(dataGridCell.value.lastName, nameLimit: 15)}",
                        textAlign: TextAlign.left,
                        style: GTTextStyle.subtitle2,
                      ),
                    ),
                    FittedBox(
                      fit: BoxFit.scaleDown,
                      child: Text(
                        "${StringHelper.shortName(dataGridCell.value.firstName, nameLimit: 15)}",
                        textAlign: TextAlign.left,
                        style: GTTextStyle.body,
                      ),
                    ),
                  ],
                )
              ]);
        }
      }
      if (dataGridCell.columnName == 'birthdate') {
        if (dataGridCell.value == null) return Container();
        return Container(
            alignment: Alignment.centerLeft,
            padding: EdgeInsets.symmetric(horizontal: 16.0),
            child: Text(
              _dateFormatter.format(dataGridCell.value),
              // overflow: TextOverflow.ellipsis,
              style: GTTextStyle.body,
              softWrap: false,
            ));
      }

      if (dataGridCell.columnName == 'phone') {
        if (dataGridCell.value == null) return Container();
        return InkWell(
          onTap: () {
            String phoneNumber = dataGridCell.value;
            phoneNumber = phoneNumber.replaceAll(" ", "").replaceAll(".", "");
            _launchCaller('tel:${phoneNumber}');
          },
          child: Container(
              alignment: Alignment.centerLeft,
              padding: EdgeInsets.symmetric(horizontal: 16.0),
              child: Text(
                dataGridCell.value.toString(),
                // overflow: TextOverflow.ellipsis,
                style: GTTextStyle.body,
                softWrap: false,
              )),
        );
      }

      if (dataGridCell.columnName == 'email') {
        if (dataGridCell.value == null) return Container();
        return InkWell(
          onTap: () {
            String val = dataGridCell.value;
            val = val.replaceAll(" ", "");
            _launchCaller('mailto:${val}');
          },
          child: Container(
              alignment: Alignment.centerLeft,
              // The autoFitPadding and the cell padding value should be same.
              padding: EdgeInsets.symmetric(horizontal: 16.0),
              child: Text(
                // dataGridCell.value.toString(),
                "[email protected]",
                // overflow: TextOverflow.ellipsis,
                style: GTTextStyle.body,
                softWrap: false,
              )),
        );
      }

      if (dataGridCell.columnName == 'height') {
        if (dataGridCell.value == null) return Container();
        return Container(
            alignment: Alignment.centerLeft,
            padding: EdgeInsets.symmetric(horizontal: 16.0),
            child: Text(
              dataGridCell.value.toString(),
              // overflow: TextOverflow.ellipsis,
              style: GTTextStyle.body,
              softWrap: false,
            ));
      }

      return Container();
    }).toList());
  }
}

Solution

  • You are using a different text style for the cell widget. By default, the cell width is calculated based on the default text style. To calculate the cell width based on a different TextStyle, just override the computeHeaderCellWidth method for the header and the computeCellWidth method for the cell and return the super method with the required TextStyle. Please check the following sample and code snippet.

    In DataGrid:

    
      final CustomColumnSizer _customColumnSizer = CustomColumnSizer();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('Flutter SfDataGrid'),
          ),
          body: SfDataGrid(
              source: _employeeDataSource,
              columns: getColumns,
              columnSizer: _customColumnSizer,
              columnWidthMode: ColumnWidthMode.auto),
        );
      }
    
    
    
    class EmployeeDataSource extends DataGridSource {
    
    …
    
      @override
      DataGridRowAdapter? buildRow(DataGridRow row) {
        return DataGridRowAdapter(
            cells: row.getCells().map<Widget>((dataGridCell) {
          return Container(
              alignment: Alignment.center,
              padding: const EdgeInsets.symmetric(horizontal: 16.0),
              child: Text(
                dataGridCell.value.toString(),
                style: const TextStyle(fontWeight: FontWeight.bold),
                softWrap: false,
              ));
        }).toList());
      }
    }
    
    

    In ColumnSizer:

    class CustomColumnSizer extends ColumnSizer {
      @override
      double computeHeaderCellWidth(GridColumn column, TextStyle style) {
        style = const TextStyle(fontWeight: FontWeight.bold);
    
        return super.computeHeaderCellWidth(column, style);
      }
    
      @override
      double computeCellWidth(GridColumn column, DataGridRow row, Object? cellValue,
          TextStyle textStyle) {
        textStyle = const TextStyle(fontWeight: FontWeight.bold);
    
        return super.computeCellWidth(column, row, cellValue, textStyle);
      }
    }
    
    

    Sample Link: https://www.syncfusion.com/downloads/support/directtrac/general/ze/main-621685425

    Also, we have already provided examples in our UG documentation. Please go through this,

    UG Documentation: https://help.syncfusion.com/flutter/datagrid/columns-sizing?cs-save-lang=1&cs-lang=dart#autofit-calculation-based-on-different-textstyle

    We hope this helps. Please let us know if you require any further assistance on this.