Master Detail in AdapTable

You can leverage the master detail functionality of Infinite Table in AdapTable to show a detail grid for each row in the main grid.

To implement master detail, you need to intercept the InfiniteTable component and hook the detail rendering into that.

Intercepting the InfiniteTable rendering
import { Adaptable, AdaptableProps } from '@adaptabletools/adaptable'

const CustomComponents: AdaptableProps<DATA_TYPE>['components'] = {
  InfiniteTable: (props) => {
    // you can add your custom logic here
    return <InfiniteTable {...props} />
  }
}
<Adaptable.Provider
  data={[...]} // DATA_TYPE[]
  primaryKey="id"
  adaptableId={`custom-infinite-component`}
  defaultState={state}
  components={CustomComponents}
>
  <Adaptable.UI />
</Adaptable.Provider>

Note

Prior to version 0.5.0, the components prop had to be passed to the <Adaptable.UI /> component. Starting with version 0.5.0, the components prop should be passed to the <Adaptable.Provider /> component.

Take a look at the example below to see a fully working master detail grid. The master grid is your Adaptable DataGrid configuration, while the detail grid is configured to render a custom InfiniteTable component.

Master Detail demo
Fork

The main Adaptable DataGrid shows a list of license types. Expand each license type to see a detail grid with web frameworks that use that license type.

Note

In future releases, we will provide a more streamlined way to work with master detail grids. In the current version, you have to intercept the InfiniteTable rendering and do the wiring yourself, as demonstrated in the example above.

Intercepting the InfiniteTable rendering

As detailed above, for setting up master-detail, the first step is to intercept the rendering of the InfiniteTable component and define the rowDetailRenderer

const components: AdaptableProps<License>['components'] = {
  InfiniteTable: (props: InfiniteTableProps<License>) => {
    const columns = props.columns;

    // make the first column render the row detail icon
    columns[Object.keys(columns)[0]].renderRowDetailIcon = true

    return (
      <InfiniteTable<License>
        {...props}
        columns={columns}
        {/* define the rowDetailRenderer */}
        rowDetailRenderer={rowDetailRenderer}
      />
    );
  },
};

export default function App() {
  return (
    <>
      <Adaptable.Provider
        data={licenses}
        primaryKey="id"
        adaptableId={`custom-infinite-component`}
        licenseKey={process.env.NEXT_PUBLIC_ADAPTABLE_LICENSE_KEY}
        defaultState={state}
        components={components}
      >
        <Adaptable.UI  />
      </Adaptable.Provider>
    </>
  );
}

Note

Make sure you don't forget to make one of the columns render the row detail icon. This is done by setting the renderRowDetailIcon property to true on the column definition - see detailed steps in the Infinite Table master-detail documentation page.

After you define the custom InfiniteTable component rendering, make sure you define the rowDetailRenderer function. This function will be called for each row in the main grid and should return the detail grid for that row.

The rowDetailRenderer function can render a detail grid or any valid JSX
function rowDetailRenderer(rowInfo: InfiniteTableRowInfo<License>) {
  // you can
  return (
    <div
      style={{
        display: 'flex',
        flex: 1,
        flexFlow: 'column',
        height: '100%',
      }}
    >
      <h3>Web frameworks ({rowInfo.data!.type})</h3>
      <DataSource<WebFramework> data={detailDetaSource} primaryKey={'id'}>
        <InfiniteTable<WebFramework> columns={detailColumns} />
      </DataSource>
    </div>

Note

The data prop of the detail <DataSource /> is a function that can return a promise, and it has access to the masterRowInfo object, which contains the information about the master row.

You can read more about loading the detail DataSource in the Infinite Table documentation.