bosskmk / pluto_grid

PlutoGrid is a dataGrid for flutter that can be controlled by the keyboard on desktop and web. Of course, it works well on Android and IOS.

Home Page:https://pluto.weblaze.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unhandled Exception when selecting row

hamzaj9 opened this issue · comments

I just got an Unhandled Exception when selecting a row, keep selecting a row but different columns it will keep giving the same exception.

[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: LateInitializationError: Field '_column@454200100' has not been initialized.
#0 PlutoCell._column (package:pluto_grid/src/model/pluto_cell.dart)
#1 PlutoCell.column (package:pluto_grid/src/model/pluto_cell.dart:44:29)
#2 ColumnState.currentColumn (package:pluto_grid/src/manager/state/column_state.dart:318:54)
#3 EditingState.autoEditing (package:pluto_grid/src/manager/state/editing_state.dart:54:23)
#4 CellState.setCurrentCell (package:pluto_grid/src/manager/state/cell_state.dart:213:16)
#5 PlutoGridCellGestureEvent._selectMode (package:pluto_grid/src/manager/event/pluto_grid_cell_gesture_event.dart:142:20)
#6 PlutoGridCellGestureEvent._onTapUp (package:pluto_grid/src/manager/event/pluto_grid_cell_gesture_event.dart:52:7)
#7 PlutoGridCellGestureEvent.handler (package:pluto_grid/src/manager/event/pluto_grid_cell_gesture_event.dart:24:9)
#8 PlutoGridEventManager._handler (package:pluto_grid/src/manager/pluto_grid_event_manager.dart:77:11)

NOTE: the application don't quit. and the debugger can't catch anything.

PlutoGrid version
PlutoGrid version is 5.0.1

OS
Windows 10

See the history of the same issue below.

If you still have problems, please attach a reproducible example code.

#499

commented

PlutoGrid : 5.0.0/5.0.2

E/flutter (12912): #0      PlutoCell._column (package:pluto_grid/src/model/pluto_cell.dart)
E/flutter (12912): #1      PlutoCell.column (package:pluto_grid/src/model/pluto_cell.dart:44:29)
E/flutter (12912): #2      ColumnState.currentColumn (package:pluto_grid/src/manager/state/column_state.dart:318:54)
E/flutter (12912): #3      EditingState.autoEditing (package:pluto_grid/src/manager/state/editing_state.dart:54:23)
E/flutter (12912): #4      CellState.setCurrentCell (package:pluto_grid/src/manager/state/cell_state.dart:213:16)
E/flutter (12912): #5      PlutoGridCellGestureEvent._selectMode (package:pluto_grid/src/manager/event/pluto_grid_cell_gesture_event.dart:142:20)
E/flutter (12912): #6      PlutoGridCellGestureEvent._onTapUp (package:pluto_grid/src/manager/event/pluto_grid_cell_gesture_event.dart:52:7)
E/flutter (12912): #7      PlutoGridCellGestureEvent.handler (package:pluto_grid/src/manager/event/pluto_grid_cell_gesture_event.dart:24:9)
E/flutter (12912): #8      PlutoGridEventManager._handler (package:pluto_grid/src/manager/pluto_grid_event_manager.dart:77:11)
  const CoordListView({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => CoordListViewState();
}

class CoordListViewState extends State<CoordListView> {
  final List<PlutoColumn> columns = [];
  final List<PlutoRow> rows = [];
  late StreamSubscription removeKeyboardListener;

  @override
  void initState() {
    super.initState();

    BuildContext context = globalKey.currentContext!;
    columns.addAll(<PlutoColumn>[
      newColumn(
          width: 110.w,
          title: context.s.pointId,
          field: ColumnType.name,
          frozen: PlutoColumnFrozen.start,
          enableRowChecked: true),
      newColumn(
        width: 69.w,
        title: context.s.pointType,
        field: ColumnType.type,
      ),
      newColumn(
        width: 102.w,
        title: context.s.enuOfnName,
        field: ColumnType.northCoord,
      ),
      newColumn(
        width: 102.w,
        title: context.s.enuOfeName,
        field: ColumnType.eastCoord,
      ),
      newColumn(
        width: 102.w,
        title: context.s.enuOfuName,
        field: ColumnType.height,
      ),
      newColumn(
        width: 102.w,
        title: context.s.latitude,
        field: ColumnType.latitude,
      ),
      newColumn(
        width: 102.w,
        title: context.s.longitude,
        field: ColumnType.longitude,
      ),
      newColumn(
        width: 102.w,
        title: context.s.earthHeightM,
        field: ColumnType.earthHeight,
      ),
      newColumn(
        width: 102.w,
        title: context.s.imageMarking,
        field: ColumnType.imageTags,
      ),
    ]);
  }

  @override
  void dispose() {
    removeKeyboardListener.cancel();

    super.dispose();
  }

  void handleKeyboard(PlutoKeyManagerEvent event) {
    debugPrint("handleKeyboard:${event.event.character}");
  }

  PlutoColumn newColumn({
    required String title,
    field,
    required double width,
    PlutoColumnFrozen frozen = PlutoColumnFrozen.none,
    bool enableRowChecked = false,
  }) {
    return PlutoColumn(
      backgroundColor: const Color(0xFFEDF2FF),
      enableContextMenu: false,
      enableFilterMenuItem: false,
      frozen: frozen,
      readOnly: true,
      enableDropToResize: false,
      enableColumnDrag: false,
      width: width,
      enableRowChecked: enableRowChecked,
      enableAutoEditing: false,
      enableEditingMode: false,
      title: title,
      field: field,
      type: PlutoColumnType.text(),
    );
  }

  PlutoGridStateManager? stateManager;

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<CoordRepositoryBloc, CoordRepositoryState>(
      builder: (context, state) {
        updateRow(state);
        return Container(
          margin: EdgeInsets.only(left: 14.w, right: 14.w, bottom: 23.w),
          child: PlutoGrid(
            columns: columns,
            rows: rows,
            onLoaded: (PlutoGridOnLoadedEvent event) {
              stateManager = event.stateManager;
              removeKeyboardListener = stateManager!.keyManager!.subject.stream.listen(handleKeyboard);
              stateManager?.setSelectingMode(PlutoGridSelectingMode.row);
            },
            onChanged: (event) {
              debugPrint("PlutoGrid:onChanged");
            },
            mode: PlutoGridMode.select,
            onSelected: (event) {
              debugPrint("PlutoGrid:onSelected");
            },
            configuration: PlutoGridConfiguration(
              // columnSize: const PlutoGridColumnSizeConfig(autoSizeMode: PlutoAutoSizeMode.scale),
              style: PlutoGridStyleConfig(
                  oddRowColor: Colors.white,
                  evenRowColor: const Color.fromRGBO(243, 244, 249, 1),
                  gridBorderColor: const Color.fromRGBO(231, 236, 247, 1),
                  borderColor: const Color.fromRGBO(231, 236, 247, 1),
                  enableColumnBorderHorizontal: true,
                  enableColumnBorderVertical: true,
                  columnTextStyle: TextStyle(
                    color: SrtkTheme.colors.textBlack,
                    decoration: TextDecoration.none,
                    fontSize: 13.sp,
                    fontWeight: FontWeight.w600,
                  ),
                  cellTextStyle: TextStyle(
                    color: SrtkTheme.colors.textGray,
                    fontSize: 13.sp,
                  )),
            ),
          ),
        );
      },
    );
  }

  void updateRow(CoordRepositoryState state) async {
    if (stateManager == null) return;
    state.points
        .map((p) => PlutoRow(
              cells: {
                ColumnType.name: PlutoCell(value: p.name),
                ColumnType.type: PlutoCell(value: p.type),
                ColumnType.northCoord: PlutoCell(value: p.enu?.n ?? "--"),
                ColumnType.eastCoord: PlutoCell(value: p.enu?.e ?? "--"),
                ColumnType.height: PlutoCell(value: p.enu?.u ?? "--"),
                ColumnType.latitude: PlutoCell(value: p.blh?.b ?? "--"),
                ColumnType.longitude: PlutoCell(value: p.blh?.l ?? "--"),
                ColumnType.earthHeight: PlutoCell(value: p.blh?.h ?? "--"),
                ColumnType.imageTags: PlutoCell(value: p.imagePaths.length),
              },
            ))
        .forEach((row) {
      stateManager?.refRows.add(row);
    });
  }
}

@Comanx

When adding rows, you must use the stateManager.insertRows, prependRows, appendRows methods.
Adding a job to stateManager.refRows requires extra work.
(stateManager.initializeRows or initializeRowsAsync)

The link below is an example of adding a row with the refRows.addAll method after setting the necessary settings for the row with PlutoGridStateManager.initializeRowsAsync.
https://weblaze.dev/pluto_grid/build/web/#feature/add-rows-asynchronously

commented

@bosskmk Thank you! It works.

Added to the document how to add or remove columns and rows after setting them.

https://pluto.weblaze.dev/add-and-remove-columns-and-rows

Code:

  final List<PlutoColumn> columns = [];
  final List<PlutoRow> rows = [];
  static PlutoGridStateManager? stateManager = null;

void ReloadStudents() async {
    stateManager?.setShowLoading(true);
    rows.clear();
    var results = await Config.conn!.query('select * from student');
    for (var row in results) {
      int id = row["sid"];
      String name = row["name"];
      String fatherName = row["fatherName"];
      String phone = row["phone"];
      String fphone = row["fphone"];
      String address = row["address"];
      DateTime dob = row["dob"];

      rows.add(PlutoRow(
        cells: {
          "dob" : PlutoCell(value: formatDate(dob)),
          "address" : PlutoCell(value: address),
          "fphone" : PlutoCell(value: fphone),
          "phone" : PlutoCell(value: phone),
          "fatherName" : PlutoCell(value: fatherName),
          "name" : PlutoCell(value: name),
          "id" : PlutoCell(value: id),
        },
      ));
    }
    stateManager?.removeAllRows(notify: false);
    stateManager?.appendRows(rows);
    stateManager!.setShowLoading(false, notify: true);
  }
PlutoGrid grid = PlutoGrid(
      columns: columns,
      rows: [], //i was using my variable rows here
      configuration: const PlutoGridConfiguration(
        columnSize: PlutoGridColumnSizeConfig(
          autoSizeMode: PlutoAutoSizeMode.scale,
          resizeMode: PlutoResizeMode.normal,
        ),
        style: PlutoGridStyleConfig(rowHeight: 30),
        scrollbar: PlutoGridScrollbarConfig(isAlwaysShown: true),
        columnFilter: PlutoGridColumnFilterConfig()
      ),
      onSelected: (PlutoGridOnSelectedEvent event){
        PlutoRow? r = event.row;
        int id = r?.cells["id"]!.value;
        String name = r?.cells["name"]!.value;
        String fatherName = r?.cells["fatherName"]!.value;
        String phone = r?.cells["phone"]!.value;
        String fphone = r?.cells["fphone"]!.value;
        String address = r?.cells["address"]!.value;
        DateTime dob = DateTime.parse(r?.cells["dob"]!.value);
        if(name.isNotEmpty) {
          Config.selectedStudent = Student(id: id, name: name, fatherName: fatherName, phone: phone, fphone: fphone, address: address, dob: dob);
          context.read<Student>().notifyListeners();
        }
      },
      onLoaded: (PlutoGridOnLoadedEvent event) {
        event.stateManager.setSelectingMode(PlutoGridSelectingMode.row);
        stateManager = event.stateManager;
        stateManager!.notifyListeners();
        stateManager!.setShowLoading(true);
        stateManager!.setGridMode(PlutoGridMode.select);
        PlutoGridSelectingMode gridSelectingMode = PlutoGridSelectingMode.horizontal;
        stateManager!.setSelectingMode(gridSelectingMode);
        stateManager!.setShowColumnFilter(true);
      },
      mode: PlutoGridMode.select,
      rowColorCallback: (rowColorContext) {
        if(rows.indexOf(rowColorContext.row) % 2 == 0){
          return lightBlue;
        }
        return Colors.white;
      },
    );

i was not using

    stateManager?.removeAllRows(notify: false);
    stateManager?.appendRows(rows);

i was just defining the Grid with the variable rows that getting filled in ReloadStudents function

now my issue is solved. but is this good for performance?
Note: this issue never happen in PlutoGrid 4.0.1

@bosskmk Thanks for helping and keeping this widget updated.

PlutoCell of PlutoGrid refers to the column and row to which it belongs.
This is set dynamically at runtime when creating a grid or adding columns, rows, etc.

Therefore, you need to add columns or rows through the stateManager method.

It's not a performance issue, it's a structural issue with the behavior of the grid.
It is also mentioned in the docs, but when adding a large number of rows initially or afterward, the CPU workload is high and the UI can freeze.

That's why there is a method PlutoGridStateManager.initializeRowsAsync that adds rows asynchronously.

Please refer to the documentation for details.

okay, thanks. I will close this issue.

@hamzaj9
In addition, the odd/even color of the row can be set with the oddRowColor and evenRowColor properties in the style of configuration. (instead of rowColorCallback)

configuration: PlutoGridConfiguration(
  style: PlutoGridStyleConfig(
    oddRowColor: Colors.amber,
    evenRowColor: const Color(0xFFF6F6F6),
  ),

yes i saw it in @Comanx code and i used it directly.

one more question, onSelected method triggered after 2 clicks on the row, can't we make it by 1 click only?

mode: PlutoGridMode.selectWithOneTap,

still trigger after 2 clicks

i need to click twice on the same cell to trigger it

mode: PlutoGridMode.selectWithOneTap,

If this is set, the onSelected callback works with a single tap.
If not, try debugging your code.
It seems that the problem is not with the PlutoGrid.

i tried to debug. it triggered after 2 taps :!

i saw the problem

onLoaded: (PlutoGridOnLoadedEvent event) {
        event.stateManager.setSelectingMode(PlutoGridSelectingMode.row);
        stateManager = event.stateManager;
        stateManager!.notifyListeners();
        stateManager!.setShowLoading(true);
        stateManager!.setGridMode(PlutoGridMode.selectWithOneTap);
        PlutoGridSelectingMode gridSelectingMode = PlutoGridSelectingMode.row;
        stateManager!.setSelectingMode(gridSelectingMode);
        stateManager!.setShowColumnFilter(true);
      },
      mode: PlutoGridMode.selectWithOneTap,

i was using mode and stateManager!.setGridMode(PlutoGridMode.select); in the same time. i changed the mode, but didn't see that i re-setting it using stateManager.

thanks.

Quick question, do you know how to make the plutogrid fill the whole responsiveGrid (https://pub.dev/packages/responsive_grid)?
i want to make it full height and width inside the ResponsiveGridCol