This document explains how the grid works on the Dart side. Also, it can be a development guide when you want to be a grid contributor. This document will be continuously updated, and any suggestions would be helpful.
Below you will find some quick definitions to help you read through the document.
Block | A grid can have many rows. Rows are therefore grouped into Blocks in order to make things more efficient. |
---|---|
Cache classes | Aim to reduce the time cost of getting data from the backend. |
Cell | A Cell is one individual cell in a grid. You can see more in the Cell section. |
Column | A column is a theoretical representation of data, however, there is no Column class. |
Field | A Field represents the configuration of a column. You can see more in the Field section. |
Grid | A Grid type is a simple representation of items placed in columns and rows. It is not a spreadsheet. You can see more in the Grid section |
Header | @@@ |
Row | A Row represents a group of related data |
At its core, a Grid type is a simple representation of items placed in columns and rows. It is not a spreadsheet.
Another name for a column is Field. A column's configuration is defined in the Field class. It is important to note though that although a grid has the concept of columns, there are no actual Column classes.
A user can add a Row, and then define the data in each of the cells created for the Grid's Fields in that row.
A Grid has a list of Blocks, each Block has a list of Rows.
{% hint style="info" %} Classes with a PB suffix are generated in protobuf format. You could check the protobuf.md document out if you are interested in how the protobuf classes are generated. {% endhint %}
When you open a grid, a GridBloc
will be initialized. There are four cache classes, as shown in the diagram above.
-
GridFieldCache
- Listens to the
Field
's changes. - Updates the
Field
according to theGridFieldChangesetPB
.
- Listens to the
-
GridBlockCache
A Grid contains many
Block
s, eachBlock
has aGridRowCache
.- Listens to the
Block
's changeset. - Updates the
GridRowCache
according to theGridBlockChangesetPB
. The changeset contains the ids of inserted/deleted/updatedRows
.
- Listens to the
-
GridRowCache
- Caches the
Block
'sRow
s in memory. - A
Row
contains manyCells, each
Cellwill be cached in the
GridCellCache`. - Allows to insert/delete/update
Row
s.
- Caches the
-
GridCellCache
- Caches each
Cell
byGridCellCacheKey
in memory. - Allows to remove/insert
Cell
s.
- Caches each
A Grid
can hold many thousands of Row
s. In order to streamline the fetching of data, these Row
s are split up and contained in Block
s.
A Grid
can contain many Block
s, each Block
has a GridRowCache
. For the moment, we only support having one Block
in the Grid. This will cause a limitation on the number of rows that a user can create, however, this limitation will be lifted in the future.
A Field
represents a column's configuration. It will contain the column's name, id, width, type (as defined in FieldType), etc.
A Field
is not a column of data, it does not contain a list of Cell
s.
A Field
has a FieldType
. The FieldType
defines the kind of data contained in a column. For example, a column may contain dates, numbers, text, multi-select list, etc.
Certain field types have user-defined options such as color, date format, number format, or a list of values for a multi-select list. These options are defined within a specialization of the FieldTypeOption
class.
Each field has its TypeOptionBuilder
in the backend that is used to parse the bytes into corresponding FieldTypeOption.
FieldEditor
A FieldEditor
is a widget that is used to edit the field's shared properties. Such as the name of the field, etc. It uses the FieldTypeOptionEditor
to customize the UI for each field.
FieldEditorBloc
FieldEditorBloc
uses a TypeOptionDataController
to listen for changes to a Field
or perform a rename operation. It will notify the widget to rebuild if its state has changed.
TypeOptionDataController
Defines how to update a Field
's properties. Such as the name, the field, and the type option data.
IFieldTypeOptionLoad
Defines how to load a Field
's type option data. For example, when we create a new Field
, we use NewTypeOptionLoader
. We use FieldTypeOptionLoader
to load the existing Field
's type option data.
FieldTypeOptionEditor
FieldTypeOptionEditor
is a widget that provides a custom UI for each Field
. You can provide a custom UI by extending the TypeOptionWidgetBuilder
As the image below shows, we have many TypeOptionWidgetBuilder
implementations.
The widget returned by TypeOptionWidgetBuilder
use TypeOptionWidgetContext
as its data model. For example, DateTypeOptionWidget
uses DateTypeOptionContext
that extends the TypeOptionWidgetContext
.
TypeOptionWidgetContext
uses TypeOptionDataParser
to parse the generic data, List, to specific data type. As the image below shows, each TypeOptionContext
must have a corresponding TypeOptionDataParser
.
A Row
represents a group of related Cells
.
RowService
RowService
handles up the logic to interact with the backend. It allows creating, duplicating, deleting, and moving the row operations.
GridRowCache
Caching the rows in memory to reduce the cost of getting data from the backend. (as defined in the Cache)
GridCellBuilder
- A
Row
has a list ofCell
s. It uses theGridCellBuilder
to build the customCell
according to the field type. Each cell should extend theGridCellWidget
interface.
A Cell
is one individual cell in a grid. The number of Cell
s in a Row
is equal to the number of Field
s in the Grid
. We define the GridCellWidget
that defines the shared behaviors. Such as CellAccessory
, CellEditable
, and CellShortcuts
.
Let's look at the select GridSingleSelectCell
and find out how it works. When a user clicks a cell, the SelectOptionCellEditor
will show up.
SelectOptionCellEditor
is a widget that defines the UI when editing the cell.SelectOptionCellEditorBloc
binds the UI and the data, theSelectOptionCellEditor
will be rebuilt if the bloc state changes.SelectOptionService
handles up the logic for deleting, updating the select option with the backend.GridSelectOptionCellController
useIGridCellController
to implement the cell's operations.
IGridCellController
- Allows getting Read/Write cell data.
- Listens to the cell date change.
- Allows getting the corresponding field type option data that is parsed by the
TypeOptionDataParser
. - Listens to the field event and loads the cell data if needed. For example, the numbered cell should reload when the number format is changed.
IGridCellDataParser
Allow getting the cell data and then parsing into a specific type.
IGridCellDataParser
The implementation of IGridCellDataParser
will parse the List<int>
into specific cell data. For example, the SelectOptionCellDataParser
will parse the List into SelectOptionCellDataPB
.
IGridCellDataPersistence
We can use CellDataPersistence that implements the IGridCellDataPersistence
to perform normal save operation.
Also, implement the IGridCellDataPersistence
to provide custom data saving operation. Just like the DateCellDataPersistence
does.
CellService
Handling the logic for reading and writing the cell data with the backend.