# Disabled Rows

Canonical page: https://infinite-table.com/docs/learn/rows/disabled-rows

Disabling rows allows you to have some rows that are not selectable, not clickable, not reacheable via keyboard navigation and other interactions.

The `DataSource` manages the disabled state of rows, via the [`defaultRowDisabledState`](https://infinite-table.com/docs/reference/datasource-props/index.md#defaultRowDisabledState) (uncontrolled) prop and [`rowDisabledState`](https://infinite-table.com/docs/reference/datasource-props/index.md#rowDisabledState) (controlled) prop.

```tsx
<DataSource<DATA_TYPE>
  idProperty="id"
  data={[]}
  defaultRowDisabledState={{
    enabledRows: true,
    disabledRows: ['id1', 'id4', 'id5']
  }}
/>
  <InfiniteTable<DATA_TYPE>
    {/* ... */}
  />
</DataSource>
```

In addition to using the [`defaultRowDisabledState`](https://infinite-table.com/docs/reference/datasource-props/index.md#defaultRowDisabledState)/[`rowDisabledState`](https://infinite-table.com/docs/reference/datasource-props/index.md#rowDisabledState) props, you can also specify the [`isRowDisabled`](https://infinite-table.com/docs/reference/datasource-props/index.md#isRowDisabled) function prop, which overrides those other props and ultimately determines whether a row is disabled or not.

**Example: Specify some rows as initially disabled**

```tsx
import * as React from 'react';

import {
  DataSource,
  DataSourceData,
  InfiniteTable,
  InfiniteTablePropColumns,
} from '@infinite-table/infinite-react';

type Developer = {
  id: number;
  firstName: string;
  lastName: string;

  currency: string;
  preferredLanguage: string;
  stack: string;
  canDesign: 'yes' | 'no';

  salary: number;
};

const data: DataSourceData<Developer> = () => {
  return fetch(process.env.NEXT_PUBLIC_BASE_URL + `/developers1k-sql?`)
    .then((r) => r.json())
    .then((data: Developer[]) => data);
};

const columns: InfiniteTablePropColumns<Developer> = {
  id: {
    field: 'id',
    type: 'number',
    defaultWidth: 100,
  },
  salary: {
    defaultFilterable: true,
    field: 'salary',
    type: 'number',
  },

  firstName: {
    field: 'firstName',
  },
  stack: { field: 'stack' },
  currency: { field: 'currency' },
};

export default () => {
  return (
    <>
      <DataSource<Developer>
        data={data}
        primaryKey="id"
        defaultRowDisabledState={{
          enabledRows: true,
          disabledRows: [1, 3, 4, 5],
        }}
      >
        <InfiniteTable<Developer>
          debugId="initialRowDisabledState-example"
          columnDefaultWidth={120}
          columnMinWidth={50}
          columns={columns}
          keyboardNavigation="row"
        />
      </DataSource>
    </>
  );
};
```

## Using disabled rows while rendering

When rendering a cell, you have access to the row disabled state - the [`InfiniteTableRowInfo`](https://infinite-table.com/docs/reference/type-definitions/index.md#InfiniteTableRowInfo) type has a `rowDisabled` property which is true if the row is disabled.

**Example: Using the row disabled state while rendering**

  This example uses custom rendering for the `firstName` column to render an emoji for disabled rows.

```tsx
import * as React from 'react';

import {
  DataSource,
  DataSourceApi,
  DataSourceData,
  InfiniteTable,
  InfiniteTablePropColumns,
} from '@infinite-table/infinite-react';

type Developer = {
  id: number;
  firstName: string;
  lastName: string;

  currency: string;
  preferredLanguage: string;
  stack: string;
  canDesign: 'yes' | 'no';

  salary: number;
};

const data: DataSourceData<Developer> = () => {
  return fetch(process.env.NEXT_PUBLIC_BASE_URL + `/developers1k-sql?`)
    .then((r) => r.json())
    .then((data: Developer[]) => data);
};

const columns: InfiniteTablePropColumns<Developer> = {
  id: {
    field: 'id',
    type: 'number',
    defaultWidth: 100,
  },
  salary: {
    defaultFilterable: true,
    field: 'salary',
    type: 'number',
  },

  firstName: {
    field: 'firstName',
    renderValue: ({ rowInfo, value }) => {
      return `${value} ${rowInfo.rowDisabled ? '🚫' : ''}`;
    },
  },
  stack: { field: 'stack' },
  currency: { field: 'currency' },
};

export default () => {
  const [dataSourceApi, setDataSourceApi] =
    React.useState<DataSourceApi<Developer>>();
  return (
    <>
      <button
        onClick={() => {
          dataSourceApi?.enableAllRows();
        }}
      >
        Enable all rows
      </button>
      <button
        onClick={() => {
          dataSourceApi?.disableAllRows();
        }}
      >
        Disable all rows
      </button>
      <DataSource<Developer>
        onReady={setDataSourceApi}
        data={data}
        primaryKey="id"
        defaultRowDisabledState={{
          enabledRows: [1, 2, 3, 5],
          disabledRows: true,
        }}
      >
        <InfiniteTable<Developer>
          debugId="custom-rendering-for-disabled-rows-example"
          columnDefaultWidth={120}
          columnMinWidth={50}
          columns={columns}
          keyboardNavigation="row"
        />
      </DataSource>
    </>
  );
};
```

## Using the API to enable/disable rows

You can use the `DataSourceApi` to enable or disable rows programmatically.

[`setRowEnabled`](https://infinite-table.com/docs/reference/datasource-api/index.md#setRowEnabled)

```tsx
dataSourceApi.setRowEnabled(rowId, enabled);

```

[`setRowEnabledAt`](https://infinite-table.com/docs/reference/datasource-api/index.md#setRowEnabledAt)

```tsx
dataSourceApi.setRowEnabledAt(rowIndex, enabled);
```

**Example: Using the API to enable/disable rows**

Use the context menu on each row to toggle the disabled state of the respective row.

```tsx
import * as React from 'react';

import {
  DataSource,
  DataSourceApi,
  DataSourceData,
  InfiniteTable,
  InfiniteTablePropColumns,
} from '@infinite-table/infinite-react';

type Developer = {
  id: number;
  firstName: string;
  lastName: string;

  currency: string;
  preferredLanguage: string;
  stack: string;
  canDesign: 'yes' | 'no';

  salary: number;
};

const data: DataSourceData<Developer> = () => {
  return fetch(process.env.NEXT_PUBLIC_BASE_URL + `/developers1k-sql?`)
    .then((r) => r.json())
    .then((data: Developer[]) => data);
};

const columns: InfiniteTablePropColumns<Developer> = {
  id: {
    field: 'id',
    type: 'number',
    defaultWidth: 100,
  },
  salary: {
    defaultFilterable: true,
    field: 'salary',
    type: 'number',
  },

  firstName: {
    field: 'firstName',
    renderValue: ({ rowInfo, value }) => {
      return `${value} ${rowInfo.rowDisabled ? '🚫' : ''}`;
    },
  },
  stack: { field: 'stack' },
  currency: { field: 'currency' },
};

export default () => {
  const [dataSourceApi, setDataSourceApi] =
    React.useState<DataSourceApi<Developer>>();
  return (
    <>
      <button
        onClick={() => {
          dataSourceApi?.enableAllRows();
        }}
      >
        Enable all rows
      </button>
      <button
        onClick={() => {
          dataSourceApi?.disableAllRows();
        }}
      >
        Disable all rows
      </button>
      <DataSource<Developer>
        onReady={setDataSourceApi}
        data={data}
        primaryKey="id"
        defaultRowDisabledState={{
          enabledRows: [1, 2, 3, 5],
          disabledRows: true,
        }}
      >
        <InfiniteTable<Developer>
          debugId="using-api-to-disable-rows-example"
          getCellContextMenuItems={({ rowInfo }, { dataSourceApi }) => {
            return {
              columns: [{ name: 'label' }],
              items: [
                {
                  label: 'Disable row',
                  key: 'disable-row',
                  disabled: rowInfo.rowDisabled,
                  onAction: ({ hideMenu }) => {
                    dataSourceApi.setRowEnabledAt(rowInfo.indexInAll, false);
                    hideMenu();
                  },
                },
                {
                  label: 'Enable row',
                  key: 'enable-row',
                  disabled: !rowInfo.rowDisabled,
                  onAction: ({ hideMenu }) => {
                    dataSourceApi.setRowEnabled(rowInfo.id, true);
                    hideMenu();
                  },
                },
                {
                  label: 'Toggle row disable/enable',
                  key: 'toggle-row-disable-enable',
                  onAction: ({ hideMenu }) => {
                    dataSourceApi.setRowEnabled(
                      rowInfo.id,
                      rowInfo.rowDisabled,
                    );
                    hideMenu();
                  },
                },
              ],
            };
          }}
          columnDefaultWidth={120}
          columnMinWidth={50}
          columns={columns}
          keyboardNavigation="row"
        />
      </DataSource>
    </>
  );
};
```
