1771 Technologies Logo

Row Data Sources

Controlled Data Source

The controlled data source provides fine-grained control over the rows displayed in Graphite Grid. Graphite Grid can be modeled using the controlled data source to match your row data exactly.

To use a controlled data source, set the rowDataSource property on the grid state to an object of the form:

const source = {
    kind: "controlled",
    getRowCount: () =>  10;
    getRowNode: (p) => {
        // return a row node
    }
    getRowById: (rowId) => {
        // return a row node or null
    }
}

The above form is the minimum required setup to create a controlled data source. The full functionality of the controlled data is explained below. However, see the Server Data Source guide for specific functionality related to server-side data loading.

Row Nodes

The controlled data source provided to the grid creates the row nodes provided to Graphite Grid. A RowNode is a description of the row to display in the grid. There are two types of RowNodes:

  • RowNodeLeaf: used for rows that do not have a parent; these are the row nodes used when rows are not pivoted.
  • RowNodeBranch: used for rows that may have children rows. The children may be either a RowNodeLeaf or RowNodeBranch.

Row Node Leaf

The leaf node has the following type:

export interface RowNodeLeaf<T = unknown> {
  readonly kind: "leaf";
 
  readonly id: string;
  readonly rowIndex: number | null;
  readonly isLoading: boolean;
  readonly hasError: boolean;
  readonly context?: { [key: string]: unknown };
 
  readonly data: T;
  readonly parent: RowNodeBranch<T> | null;
  readonly rowPin: RowPinType;
  readonly editIndex: number | null;
}
  • Name
    kind
    Type
    string
    Description

    The grid uses a string to determine the 'kind' of row node it is using.

  • Name
    id
    Type
    string
    Description

    The unique identifier for the row.

  • Name
    rowIndex
    Type
    number | null
    Description

    The row index of the row. This may be null as the grid can correctly place rows without it. However, populating this field where possible is highly recommended.

  • Name
    isLoading
    Type
    boolean
    Description

    If the row is loading. It is useful when a row must be asynchronously loaded. The grid will be able to provide some feedback.

  • Name
    hasError
    Type
    boolean
    Description

    If the row has an error. It helps indicate a row has an error (normally a data loading error). The reason for the error may be stored in the context field of the row or wherever works best for your application.

  • Name
    context
    Type
    { [key: string]: unknown }
    Description

    A store for any additional data to associate with the row. Not used by Graphite Grid directly.

  • Name
    data
    Type
    T
    Description

    The data associated with the row. This will be indexed by columns in the grid via the field property.

  • Name
    parent
    Type
    RowNodeBranch | null
    Description

    The parent of this row. If the row is a child of a pivot, this property must be defined.

  • Name
    rowPin
    Type
    RowPinType
    Description

    A meta value that provides information on whether the row is pinned to the top or bottom or is not pinned. Graphite Grid does not directly use this value and relies on the data source to determine which rows should be pinned on top and bottom.

  • Name
    editIndex
    Type
    number | null
    Description

    The index to row data that this row belongs to when being edited. This property is useful when rows change order and can be edited. The edit index should refer to the original row index. This property is not required and can safely be omitted.

Best practice

Graphite Grid provides a utility function for creating leaf nodes:

import { createRowNodeLeaf } from "@1771technologies/graphite-grid-react"
 
const node = createRowNodeLeaf({ id: "<row-id>", data: ... })

Row Node Branch

The branch node has the following type:

export interface RowNodeBranch<T = unknown> {
  readonly kind: "branch";
 
  readonly id: string;
  readonly rowIndex: number | null;
  readonly isLoading: boolean;
  readonly hasError: boolean;
  readonly context?: { [key: string]: unknown };
 
  readonly pivotKey: string;
  readonly data: Record<string, unknown>;
  readonly parent: RowNodeBranch<T> | null;
}
  • Name
    kind
    Type
    string
    Description

    The grid uses a string to determine the 'kind' of row node it is using.

  • Name
    id
    Type
    string
    Description

    The unique identifier for the row.

  • Name
    rowIndex
    Type
    number | null
    Description

    The row index of the row. This may be null as the grid can correctly place rows without it. However, populating this field where possible is highly recommended.

  • Name
    isLoading
    Type
    boolean
    Description

    If the row is loading. It is useful when a row must be asynchronously loaded. The grid will be able to provide some feedback.

  • Name
    hasError
    Type
    boolean
    Description

    If the row has an error. It helps indicate a row has an error (normally a data loading error). The reason for the error may be stored in the context field of the row or wherever works best for your application.

  • Name
    context
    Type
    { [key: string]: unknown }
    Description

    A store for any additional data to associate with the row. Not used by Graphite Grid directly.

  • Name
    pivotKey
    Type
    string
    Description

    The pivot should be the value of the rowPivotKey for the branch of the row pivot model that this row represents.

  • Name
    data
    Type
    Record<string, unknown>
    Description

    A key/value pair for the row branch. The key should be the id of a column. Unlike leaf nodes, the data for branch nodes is always indexed by the column id.

  • Name
    parent
    Type
    RowNodeBranch | null
    Description

    The parent of this row. If the row is a child of a pivot, this property must be defined.

Basic Usage

An example of a controlled data source is shown below:

class ControlledSource implements RowDataSourceControlled<number[]> {
  kind = "controlled" as const;
 
  nodes: RowNodeLeaf<number[]>[];
  lookup: Record<string, RowNodeLeaf<number[]>>;
 
  constructor(data: number[][]) {
    const nodes = data.map((d, i) =>
      createRowNodeLeaf({
        id: `${i}`,
        data: d,
        editIndex: i,
        rowIndex: i,
      }),
    );
 
    this.lookup = Object.fromEntries(nodes.map((node) => [node.id, node]));
    this.nodes = nodes;
  }
 
  getRowCount = () => this.nodes.length;
  getRowById = (id: string) => this.lookup[id] ?? null;
  getRowNode = ({ rowIndex }: GetRowNodeParams<number[]>) => this.nodes[rowIndex];
}
 
export function ControlledDataSource() {
  const grid = useGraphiteGrid({
    initial: {
      columnDefinitions: [
        { id: "Alpha", field: 0 },
        { id: "Beta", field: 1 },
        { id: "Stock Price", field: 2 },
        { id: "Gamma", field: 3 },
      ],
      rowDataSource: new ControlledSource(data),
    },
  });
 
  return (
    <div style={{ height: 300 }}>
      <GraphiteGridDom state={grid} />
    </div>
  );
}

A class has been used in the example above, but a plain JavaScript object may also be used. The controlled data source above is limited and does not support all the grid functionality (such as pivots, sorting, or filtering). See the Server Data Source guide for a fully featured controlled data source.

Row Data Source Controlled Properties

Caution

Implementing a fully featured controlled data source is quite an involved task. Before doing so, it is worth considering whether the Client Data Source is sufficient for your use case.

The controlled data source has the following interface:

export interface RowDataSourceControlled<T = unknown> {
  readonly kind: "controlled";
 
  readonly init?: (api: GraphiteGridApi<T>) => void;
  readonly getRowCount: () => number;
  readonly getRowTopCount?: () => number;
  readonly getRowBottomCount?: () => number;
  readonly getRowNode: (params: GetRowNodeParams<T>) => RowNode<T>;
  readonly getRowById: (rowId: string) => RowNode<T> | null;
  readonly getAllRowIds?: () => Set<string>;
  readonly getAllChildrenIdsForRow?: (rowId: string) => string[];
  readonly getAllBranchIds?: (p: { api: GraphiteGridApi<T> }) => string[] | Promise<string[]>;
  readonly getAllBranchIdsAtDepth?: (
    params: GetAllBranchIdsAtDepth<T>,
  ) => string[] | Promise<string[]>;
  readonly refresh?: (params: { api: GraphiteGridApi }) => void;
}

A full description of each of the controlled row data source properties is provided below:

  • Name
    kind
    Type
    "controlled"
    Description

    A string indicating the type of data source. For a controlled data source, this must be "controlled".

  • Name
    init
    Type
    (api: GraphiteGridApi<T>) => void
    Description

    A data source initialization function. Graphite Grid will call this function with the Grid API. This provides an opportunity to drive data fetching with the information provided by the grid API.

  • Name
    getRowCount
    Type
    () => number
    Description

    A required callback that returns the current row count of the data source (excluding top and bottom frozen rows).

  • Name
    getRowTopCount
    Type
    () => number
    Description

    An optional callback that returns the number of rows that should be frozen to the top of the grid.

  • Name
    getRowBottomCount
    Type
    () => number
    Description

    An optional callback that returns the number of rows that should be frozen to the bottom of the grid.

  • Name
    getRowNode
    Type
    (params: GetRowNodeParams<T>) => RowNode<T>
    Description

    A callback that returns a row node for a given row index. This property is required and should be as efficient as possible.

  • Name
    getRowById
    Type
    (rowId: string) => RowNode<T> | null
    Description

    A callback that returns a row node for a given row id. It may return null if the row id is not found.

  • Name
    getAllRowIds
    Type
    () => Set<string>
    Description

    A callback that will return all the ids for rows. Necessary for supporting select all functionality. This property is optional.

  • Name
    getAllChildrenIdsForRow
    Type
    (rowId: string) => string[]
    Description

    Returns the ids of a row's children (including branch nodes). This is required for row selection and to support group selection, but otherwise may be omitted.

  • Name
    getAllBranchIds
    Type
    (p: { api: GraphiteGridApi<T> }) => string[] | Promise<string[]>
    Description

    Returns all the branch ids for the rows in the grid. This adds support for expanding all branch nodes in the grid.

  • Name
    getAllBranchIdsAtDepth
    Type
    (params: GetAllBranchIdsAtDepth<T>) => string[] | Promise<string[]>
    Description

    Returns all the branch ids for the rows in the grid at a particular level. This is required to expand all the branch nodes at a particular level.

  • Name
    refresh
    Type
    (params: { api: GraphiteGridApi }) => void
    Description

    Graphite Grid calls the refresh callback when the row data source needs to be updated. State changes, such as sort model or filter model changes, may require a view update.