Using React-Bootstrap and AG Grid
Tags: tutorial, react, aggrid
Published: 2022-07-21 09:09:59

---
title: Using React-Bootstrap and AG Grid
published: true
date: 2022-07-20 13:24:24 UTC
tags: Tutorial,React,aggrid
canonical_url: https://blog.ag-grid.com/using-react-bootstrap-and-ag-grid/
cover_image: https://blog.ag-grid.com/content/images/2022/07/react-bootstrap-aggrid-tiny.png
---

 ![Using React-Bootstrap and AG Grid](https://blog.ag-grid.com/content/images/2022/07/react-bootstrap-aggrid-tiny.png)

_This post contributed to the AG Grid blog by [Arek Nawo](https://areknawo.com/)_

[Bootstrap](https://getbootstrap.com/) is one of the most popular CSS frameworks, so it’s no surprise that many libraries integrate it with the top JavaScript UI frameworks. One such library is React-Bootstrap.

[React-Bootstrap](https://react-bootstrap.github.io/) provides Bootstrap-powered React components with built-in reactivity. Every component is compatible with Bootstrap themes, optimized for accessibility, and can be controlled with React props. As one of the oldest React component libraries, React-Bootstrap is an excellent choice for building modern, responsive UI.

In this article, you’ll learn how to integrate React-Bootstrap with [AG Grid](https://www.ag-grid.com/), a batteries-included JavaScript grid with [first-party React integration](https://www.ag-grid.com/react-data-grid/). You’ll see how easy it is to use both tools to build a compelling, user-friendly UI.

You can find the complete code for this tutorial in [this GitHub repo](https://github.com/areknawo/Using-React-Bootstrap-and-AG-Grid).

## AG Grid vs. React-Bootstrap Table

Before getting into the code, you should know the differences between AG Grid and React-Bootstrap’s built-in `Table` component.

At its core, the `Table` component is a traditional HTML table with a header, body, rows, and cells. React-Bootstrap makes the often-tedious process of creating an HTML table easier, not only with React’s reactivity and JSX but also with a faster styling process. You can set basic styles, add a row hover effect or dark theme, and make the table responsive with just a few props. However, it’s still a simple table that’s meant for basic use cases.

On the other hand, AG Grid is a full-blown, high-performance grid library. It provides you with everything you need to create an advanced, highly interactive grid-based UI, including filtering, data streaming, charting, and more. It’s your go-to solution if you need anything beyond a static table.

## Using AG Grid with React-Bootstrap

To get started, make sure you’ve got NPM v7 and Node.js v12.2.0 or newer installed. Then, run the following commands to scaffold your project using [Vite](https://vitejs.dev/)—a fast ES module-based bundler—and install necessary dependencies:

```
npm create vite project --template react
cd project
npm install
npm install bootstrap react-bootstrap ag-grid-community ag-grid-react

```

The installed dependencies include the following:

- React-Bootstrap and “vanilla” Bootstrap for CSS styles loading
- AG Grid’s core “community” package and React Data Grid for rendering

To start the development server, use `npm run dev`.

### Creating Card Container

To learn how to integrate React-Bootstrap with AG Grid, you’ll build a simple app listing countries to visit. You use React-Bootstrap to add functionality and visuals to the grid with images and buttons.

Inside the **src/App.jsx** file, you initialize AG Grid together with React-Bootstrap. Start by creating a Bootstrap card for holding the grid:

```
import Card from "react-bootstrap/Card";
import Stack from "react-bootstrap/Stack";
import "bootstrap/dist/css/bootstrap.min.css";

const App = () => {
  return (
    <Card body className="h-100">
      <Stack className="h-100">
        <Card.Title>Countries to visit</Card.Title>
        [Grid]
      </Stack>
    </Card>
  );
};

export default App;

```

Using the `Card` and `Stack` components, you just built a full-height card with vertically stacked content. The grid will be placed just below the title.

To center the card in the body, add some CSS in the **src/index.css** file:

```
html {
  height: 100%;
  width: 100%;
}
body {
  margin: 0;
  padding: 1rem;
  height: 100%;
}
#root {
  margin: auto;
  height: 100%;
  width: 100%;
  max-width: 48rem;
}

```

With these changes, the card should now look like this:

![Using React-Bootstrap and AG Grid](https://blog.ag-grid.com/content/images/2022/07/bootstrap-card-container-tiny.png)

### Creating Basic AG Grid

To add the grid to the setup, you have to create a data source, which can be done using the `useState()` hook:

```
// ...
import { useState } from "react";
// ...

const App = () => {
  const [columnDefs] = useState([
    {
      headerName: "Country",
      field: "country",
    },
    {
      headerName: "Image",
      field: "image",
      flex: 1,
    },
    {
      headerName: "Visited",
      field: "visited",
    },
  ]);
  const [rowData] = useState([
    {
      country: "United Kingdom",
      image:
        "https://images.unsplash.com/photo-1486299267070-83823f5448dd?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2371&q=80",
      visited: false,
    },
    {
      country: "United States",
      image:
        "https://images.unsplash.com/photo-1501594907352-04cda38ebc29?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80",
      visited: false,
    },
    {
      country: "India",
      visited: false,
      image:
        "https://images.unsplash.com/photo-1524492412937-b28074a5d7da?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2371&q=80",
    },
    {
      country: "Canada",
      visited: false,
      image:
        "https://images.unsplash.com/photo-1519832979-6fa011b87667?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2353&q=80",
    },
    {
      country: "Brazil",
      visited: false,
      image:
        "https://images.unsplash.com/photo-1483729558449-99ef09a8c325?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2370&q=80",
    },
    {
      country: "Germany",
      visited: false,
      image:
        "https://images.unsplash.com/photo-1554072675-66db59dba46f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2373&q=80",
    },
    {
      country: "France",
      visited: false,
      image:
        "https://images.unsplash.com/photo-1431274172761-fca41d930114?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2370&q=80",
    },
  ]);

  // ...
};
// ...

```

Each data row contains the name of the country, a related [Unsplash](https://unsplash.com/) image URL, and a Boolean indicating whether it was already visited. In addition, `columnDefs` define how the grid’s columns should be structured—e.g., their headers and width. In this case, all columns are displayed as text, with the image column taking the remaining horizontal space with `flex: 1`.

To display the grid, use the `AgGridReact` component passing the row data, column definition, and any additional properties—`rowHeight` in pixels in this case—as props:

```
// ...
import { AgGridReact } from "ag-grid-react";
import "ag-grid-community/dist/styles/ag-grid.css";
import "ag-grid-community/dist/styles/ag-theme-material.css";
// ...

const App = () => {
  // ...
  return (
    <Card body className="h-100">
      <Stack className="h-100 ag-theme-material">
        <Card.Title>Countries to visit</Card.Title>
        <AgGridReact
          columnDefs={columnDefs}
          rowData={rowData}
          rowHeight={200}
        ></AgGridReact>
      </Stack>
    </Card>
  );
};

// ...

```

The grid also comes with CSS of its own, which you also have to import. The `ag-theme-material` class on the grid’s wrapper indicates what theme to use.

The grid is now ready, but it displays all columns as text:

![Using React-Bootstrap and AG Grid](https://blog.ag-grid.com/content/images/2022/07/basic-ag-grid-setup-tiny.png)

Let’s use React-Bootstrap and replace URLs with images.

### Displaying Images

To display images in the grid, you’ll have to create a new component to be used as a cell renderer.

Create a new file at **src/ImageRenderer.jsx** with the following content:

```
import Image from "react-bootstrap/Image";
import Stack from "react-bootstrap/Stack";

const ImageRenderer = (props) => {
  return (
    <Stack direction="horizontal" className="h-100">
      <Image rounded src={props.getValue()} className="h-auto w-100" />
    </Stack>
  );
};

export default ImageRenderer;

```

Cell-renderer components receive data about the grid and current cell as props. You can use `props.getValue()` to get the cell’s current value, an image URL in this example. This value is then provided to React-Bootstrap’s `Image` component, along with other props. Additional Bootstrap class names and horizontally aligned `Stack` assure centered positioning and grid-adjusted sizing of the image.

To use `ImageRenderer` in the grid, return to **src/App.jsx** and set it as a cell renderer for the image column:

```
// ...
import ImageRenderer from "./ImageRenderer";
// ...

const App = () => {
  const [columnDefs] = useState([
    {
      headerName: "Country",
      field: "country",
    },
    {
      headerName: "Image",
      field: "image",
      flex: 1,
      // Set ImageRenderer component as cell renderer
      cellRenderer: ImageRenderer,
    },
    {
      headerName: "Visited",
      field: "visited",
    },
  ]);
  // ...
};

// ...

```

With these improvements, the grid already looks a lot better:

![Using React-Bootstrap and AG Grid](https://blog.ag-grid.com/content/images/2022/07/ag-grid-with-images-tiny.png)

### Adding Toggle Buttons

Besides seeing images, the user should be able to mark countries as visited. Currently, the visited column is empty as it contains only Boolean `false` values. To show a toggle button instead, create a new cell renderer at **src/VisitedRenderer.jsx** :

```
import ToggleButton from "react-bootstrap/ToggleButton";

const VisitedRenderer = (props) => {
  return (
    <ToggleButton
      size="sm"
      id={`visited-${props.rowIndex}`}
      type="checkbox"
      variant={props.getValue() ? "outline-primary" : "outline-secondary"}
      checked={props.getValue()}
      value="1"
      onChange={(e) => {
        props.setValue(e.currentTarget.checked);
      }}
    >
      {props.getValue() ? "YES" : "NO"}
    </ToggleButton>
  );
};

export default VisitedRenderer;

```

Using React-Bootstrap’s `ToggleButton`, you can easily create a button-style checkbox. The button is styled and labeled according to the prop’s value, which is set on every toggle with `props.setValue()`.

Pay special attention to the `id` prop. It’s important for it to be unique, as React-Bootstrap uses it as an HTML `id` attribute, matching the underlying `<input>` checkbox and button-styled `<label>`.

Now all you have to do is load the cell renderer in **src/App.jsx** , and you should see toggle buttons appear in the column:

```
// ...
import VisitedRenderer from "./VisitedRenderer";
// ...

const App = () => {
  const [columnDefs] = useState([
    {
      headerName: "Country",
      field: "country",
    },
    {
      headerName: "Image",
      field: "image",
      flex: 1,
      cellRenderer: ImageRenderer,
    },
    {
      headerName: "Visited",
      field: "visited",
      // Set VisitedRenderer component as cell renderer
      cellRenderer: VisitedRenderer,
    },
  ]);
  // ...
};

// ...

```

![Using React-Bootstrap and AG Grid](https://blog.ag-grid.com/content/images/2022/07/ag-grid-toggle-buttons-tiny.png)

### Customizing Column Header

One of many great things about AG Grid is that it’s very customizable, far beyond custom cell renderers. You can utilize this customizability together with React-Bootstrap to build—e.g., custom column headers with different functionalities.

#### Setting up External Filter

For this example, you’ll build a custom header for the visited column with the ability to filter the list for only the visited countries. Start by adding an external filter to the grid in **src/App.jsx** :

```
import { useEffect, useState, useRef } from "react";
// ...

const App = () => {
  const gridRef = useRef();
  const [filterEnabled, setFilterEnabled] = useState(false);
  // ...
  const doesExternalFilterPass = (node) => {
    return node.data.visited;
  };

  useEffect(() => {
    if (gridRef.current && gridRef.current.api) {
      gridRef.current.api.onFilterChanged();
    }
  }, [filterEnabled]);

  return (
    <Card body className="h-100">
      <Stack className="h-100">
        <Card.Title>Countries to visit</Card.Title>
        <div className="ag-theme-material h-100 w-100">
          <AgGridReact
            ref={gridRef}
            columnDefs={columnDefs}
            rowData={rowData}
            rowHeight={200}
            doesExternalFilterPass={doesExternalFilterPass}
            isExternalFilterPresent={() => filterEnabled}
          ></AgGridReact>
        </div>
      </Stack>
    </Card>
  );
};

// ...

```

In AG Grid, [external filters](https://www.ag-grid.com/react-data-grid/filter-external/) allow you to mix your custom filtering logic with the mechanisms already integrated into the grid. To enable them, you have to provide two additional props:

- `doesExternalFilterPass`: This is the actual filter function; given a node, it should return a Boolean indicating whether or not to include the row in the result.
- `isExternalFilterPresent`: This is a function returning a Boolean that informs the grid about the presence of the external filter.

In the code above, the external filter is controlled by a `filterEnabled` state property and a `doesExternalFilterPass()` function, which extracts the `visited` boolean from row data to filter the grid.

To make the grid process the filter accordingly on `filterEnabled` change, you must first inform it about a change in the filter configuration using `api.onFilterChanged()`.

The `api` object is accessible on the grid element; thus, you should use the `useRef()` hook to create a reference to it first. Then, with the `useEffect()` hook, call `api.onFilterChanged()` every time `filterEnabled` changes.

#### Adding Toggle Button Header

With the external filter ready, now it’s just a matter of creating a custom header component that will set `filterEnabled`.

In **src/VisitedHeader.jsx** , create the following component:

```
import { useState, useEffect } from "react";
import ToggleButton from "react-bootstrap/ToggleButton";

const VisitedHeader = (props) => {
  const [checked, setChecked] = useState(false);

  useEffect(() => {
    props.setFilterEnabled(checked);
  }, [checked]);

  return (
    <ToggleButton
      id="filter-visited"
      type="checkbox"
      variant={checked ? "outline-primary" : "outline-secondary"}
      checked={checked}
      value="1"
      onChange={(e) => {
        setChecked(e.currentTarget.checked);
      }}
    >
      Visited
    </ToggleButton>
  );
};

export default VisitedHeader;

```

`VisitedHeader` once again uses React-Bootstrap’s `ToggleButton` with custom `id` and value-based styling. On top of that, it has its own state property, `checked`, to keep track of the toggle button. The parent component is notified about every change with the `useEffect()` and `setFilterEnabled()` method passed through the props.

Back in the **src/App.jsx** file, you should set the header component and pass the required `setFilterEnabled` prop:

```
// ...
import VisitedHeader from "./VisitedHeader";
// ...

const App = () => {
  // ...
  const [columnDefs] = useState([
    {
      headerName: "Country",
      field: "country",
    },
    {
      headerName: "Image",
      field: "image",
      flex: 1,
      cellRenderer: ImageRenderer,
    },
    {
      headerName: "Visited",
      // Set VisitedHeader component as header component
      headerComponent: VisitedHeader,
      // Pass additional props to the header component
      headerComponentParams: {
        setFilterEnabled,
      },
      field: "visited",
      cellRenderer: VisitedRenderer,
    },
  ]);

  // ...
};

// ...

```

It’s worth noting that AG Grid also provides a distinctive `headerComponentParams` property to pass custom props to the header component (aside from the grid-provided ones). The component itself can be set using the `headerComponent` property.

The final result looks like this:

![Using React-Bootstrap and AG Grid](https://blog.ag-grid.com/content/images/2022/07/final-result-ag-grid-bootstrap-tiny.png)

## Conclusion

In this article, you’ve learned how you can use AG Grid and React-Bootstrap together, as well as how customizable AG Grid really is. By using AG Grid’s React Data Grid, you not only get a great, highly advanced grid view but also easy access to the ecosystem of the leading JS UI framework. With such powerful tools, the only limit to your app is your imagination.

AG Grid is the leading JavaScript Grid. It should be your go-to open source tool whenever you need a batteries-included grid solution, with advanced features like live data streaming, charting, editing, and more. Check out AG Grid’s [official documentation](https://www.ag-grid.com/react-data-grid/) to learn more.

<!--kg-card-end: markdown-->