Notify President Madagascar

    @onaio/drill-down-table
    TypeScript icon, indicating that this package has built-in type declarations

    1.0.6 • Public • Published

    DrillDownTable

    DrillDownTable is a bootstrap-based higher order component that works with React Table.

    It makes use of the following hooks from react-table:

    • useSortBy
    • usePagination
    • useResizeColumns
    • useFlexLayout

    Installation

    yarn add @onaio/drill-down-table

    You can opt to use the default styles by adding this to your component's file

    import '@onaio/drill-down-table/dist/table.css';

    Displaying Hierarchical Data

    DrillDownTable was made to let you easily display hierarchically structured data in nice tables that allow you to drill down through the hierarchical levels of the data.

    Data structure

    We expect the hierarchical data to be structured as expected in the adjacency list model. i.e. each record in the data will have a pointer to its parent, like so:

      id  | parent_id |      name
    ------+-----------+----------------
     3954 |           | Siavonga
     2939 |           | Chadiza
     2962 | 2939      | Sinalo
     2957 | 3954      | Mkumbuzi
     2946 | 2962      | SNL_1
     2958 | 2962      | SNL_2
     2956 | 2962      | SNL_3
     2959 | 2957      | MKU_1
     2951 | 2957      | MKU_2
     2950 | 2939      | Chanida Border
     2947 | 2939      | Chanjobwe

    Of course in javascript this same data will be represented as a list of objects, something like:

    data = [
      {
        id: 1,
        name: 'District A',
        parent_id: null,
        spray_coverage: '80%',
        spray_effectiveness: '80%'
      },
      {
        id: 4,
        name: 'HFC 1',
        parent_id: 1,
        spray_coverage: '70%',
        spray_effectiveness: '90%'
      }
    ];

    WithHeaders

    As you know, you absolutely need to define columns when working with React Table. DrillDownTable includes a columnsFromObject util that can be used to create columns from your objects

    The props

    These are:

    columns && data

    Required these 2 props should be structured as defined by react-table.

    identifierField

    Optional(string = id)

    Which field in the data represents the unique identifier for a row of data? This is optional, but if you do not define it then the default is set to id.

    parentIdentifierField

    Optional(string = parent_id)

    Which field in the data represents the unique identifier of the parent of a row of data? This is optional, but if you do not define it then the default is set to parent_id.

    rootParentId

    This defines the value of the parentIdentifierField on the highest hierarchy level of your data. This is commonly something like null or '' or 0.

    Basically it defines the first hierarchical level that you want to show on your DrillDownTable.

    This is also optional and defaults to null.

    linkerField

    Optional(string | undefined = undefined)

    When the table is rendered, you can click anywhere on a row to drill down to the next level of the hierarchy. However, you may want to display some kind of indication that it is possible to drill down on a row of data. The linkerField prop allows you to define which field should have this indicator. By default this is set to the id field.

    CellComponent

    This is a component responsible for rendering the cell in which the linkerField (above) is found. By default it just adds a caret to show if you can drill down on a row of data or not. However you can supply your own component that renders whatever else you may want - for example instead of a caret you may want to show a link. Have a look at DropDownCell for an example of how this component might look at.

    extraCellProps

    This is an object that represents extra props to be given to the CellComponent (above).

    useDrillDown

    Optional(boolean = true)

    By default DrillDownTable allows you to click on any row to drill-down to the next hierarchical level of data. This is achieved by adding a custom onClick handler to the cells that render the linker field. To switch this off and have the table render as a normal table, set useDrillDown to false.

    renderInTopFilterBar

    Optional((prop) => ReactNode | undefined = undefined)

    add a section immediately above table for filter components, through a render prop

    renderInBottomFilterBar

    Optional((prop) => ReactNode | undefined = undefined)

    add a section immediately below table for filter components, through a render prop

    nullDataComponent

    Optional(() => React.ReacNode = <default component>)

    A renderProp that renders a custom component when data is an empty array.

    loading

    Optional(boolean = false)

    A boolean switch that makes the table render a custom

    loadingComponent

    Optional(React.ElementType = <default component>)

    A custom component that should be rendered when loading is true.

    getTdProps

    optional((cell: Cell) => Dictionary | undefined = undefined)

    Use this to pass in a custom prop getter for the table cell elements.

    While the default for this is undefined, the table component does make use of a customTdProps getter that attaches a onClick handler that effects drilling down, This handler is only used when useDrillDown = true and getTdProps is undefined, otherwise if getTdProps is propped in then the component uses that as the click handler

    paginate

    optional(boolean = true)

    Tells the component if should paginate the data. setting this to false will have the component show all of its data as a single page.

    resize

    optional(boolean = true)

    Make table columns resizeable.

    hasChildren

    Optional

    This is a function that returns a boolean indicating whether or not a row of data has children i.e. should you be able to drill down using the given row?

    A sample hasChildren function looks like so:

    export function hasChildrenFunc<D extends object>(
      cellObject: Cell<D>,
      parentIdList: Array<number | string>,
      idField: string | number = ID
    ) {
      return parentIdList.includes(cellObject.row.original[idField]);
    }

    drillDownFilter

    Optional

    A custom function to override how the hierarchy is decided.

    Code examples

    Simplest example:

    import { DrillDownTable, columnsFromObjects } from '@onaio/drill-down-table/';
    
    const props = {
      columns: columnsFromObjects(data),
      data
    };
    <DrillDownTable {...props} />;

    Define location as the column where the drill-down caret will be displayed

    import { DrillDownTable, columnsFromObjects } from '@onaio/drill-down-table/';
    
    const props = {
      columns: columnsFromObjects(data),
      data,
      linkerField: 'location'
    };
    <DrillDownTable {...props} />;

    Supply columns as a prop.

    import { DrillDownTable } from '@onaio/drill-down-table/';
    
    const columns = [
      {
        Header: 'Name',
        accessor: 'location'
      },
      {
        Header: 'Spray Coverage',
        accessor: 'spray_coverage'
      }
    ];
    const props = {
      columns,
      data,
      linkerField: 'location'
    };
    <DrillDownTable {...props} />;

    Turn off clicking on a row to drill-down i.e. .

    import { DrillDownTable, columnsFromObjects } from '@onaio/drill-down-table/';
    
    const props = {
      columns: columnsFromObjects(data),
      data,
      linkerField: 'location',
      useDrillDown: false
    };
    <DrillDownTable {...props} />;

    Use a custom CellComponent and extraCellProps.

    interface NewCellComponentProps extends DropDownCellProps {
      urlPath: string;
      caret: string;
    }
    
    const NewCellComponent: React.ElementType = (props: NewCellComponentProps) => {
      const { cellValue, hasChildren, urlPath, caret } = props;
      return (
        <div>
          <span>
            {hasChildren ? (
              <a href={urlPath}>
                {cellValue} {caret}
              </a>
            ) : (
              cellValue
            )}
          </span>
        </div>
      );
    };
    
    const props = {
      columns: columnsFromObjects(data),
      CellComponent: NewCellComponent,
      data,
      extraCellProps: { urlPath: 'http://example.com', caret: <span>&#43;</span> }
    };
    <DrillDownTable {...props} />;

    Use custom hasChildren

    import { DrillDownTable, columnsFromObjects } from '@onaio/drill-down-table/';
    
    const props = {
      columns: columnsFromObjects(data),
      data: data,
      hasChildren: (item, parents, idfield) => item.original[idfield] === 10
    };
    <DrillDownTable {...props} />;

    Adding global filter components like pagination

    // write the pagination component
    const CustomPagination = (props) => {
        return <>{/* pagination JSX */}</>
    }
    
    // create a render prop that takes the [TableInstance properties](https://github.com/tannerlinsley/react-table/blob/master/docs/api/useTable.md#instance-properties) adds custom properties and passes them to the CustomPagination component
    const customRenderInFilterBar = <T extends object>(tableProps: RenderFiltersInBarOptions<T>) => {
        return (
          <div className="row">
            <div className="col">{customRenderPagination(tableProps)}</div>
          </div>
        );
      };
      let props: Dictionary = {
        columns: columnsFromObjects(jurisdictions),
        data: jurisdictions,
        useDrillDown: true,
        renderInTopFilterBar: customRenderInFilterBar,
        linkerField: 'name',
        rootParentId: '',
        renderInBottomFilterBar: customRenderInFilterBar
      };
    
    <DrillDownTable {...props} />
      );

    Keywords

    none

    Install

    npm i @onaio/drill-down-table

    DownloadsWeekly Downloads

    11

    Version

    1.0.6

    License

    Apache-2.0

    Unpacked Size

    64.4 kB

    Total Files

    26

    Last publish

    Collaborators

    • onaio