Использование React-Bootstrap и AG Grid

Этот пост подготовлен Ареком Наво для блога AG Grid

Bootstrap — один из самых популярных CSS-фреймворков, поэтому неудивительно, что многие библиотеки интегрируют его с лучшими JavaScript UI-фреймворками. Одной из таких библиотек является React-Bootstrap.

React-Bootstrap предоставляет компоненты React на базе Bootstrap со встроенной реактивностью. Каждый компонент совместим с темами Bootstrap, оптимизирован для доступности и может управляться с помощью реквизитов React. Будучи одной из старейших библиотек компонентов React, React-Bootstrap является отличным выбором для создания современного, отзывчивого пользовательского интерфейса.

В этой статье вы узнаете, как интегрировать React-Bootstrap с AG Grid, сеткой JavaScript с батарейками и интеграцией React от первого лица. Вы увидите, как легко использовать оба инструмента для создания привлекательного и удобного пользовательского интерфейса.

Полный код для этого руководства вы можете найти в этом репозитории GitHub.

AG Grid против React-Bootstrap Table

Прежде чем перейти к коду, вы должны знать различия между AG Grid и встроенным в React-Bootstrap компонентом Table.

По своей сути компонент Table представляет собой традиционную HTML-таблицу с заголовком, телом, строками и ячейками. React-Bootstrap упрощает часто утомительный процесс создания HTML-таблицы не только благодаря реактивности React и JSX, но и благодаря более быстрому процессу стилизации. Вы можете установить основные стили, добавить эффект наведения строки или темную тему, а также сделать таблицу отзывчивой с помощью всего нескольких реквизитов. Однако это все еще простая таблица, предназначенная для базовых случаев использования.

С другой стороны, AG Grid — это полноценная высокопроизводительная библиотека сетки. Она предоставляет вам все необходимое для создания продвинутого, высокоинтерактивного пользовательского интерфейса на основе сетки, включая фильтрацию, потоковую передачу данных, построение графиков и многое другое. Это ваше лучшее решение, если вам нужно что-то большее, чем статическая таблица.

Использование AG Grid с React-Bootstrap

Чтобы начать работу, убедитесь, что у вас установлены NPM v7 и Node.js v12.2.0 или новее. Затем выполните следующие команды, чтобы скомпоновать ваш проект с помощью Vite — быстрого ES-компоновщика на основе модулей — и установить необходимые зависимости:

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

Войти в полноэкранный режим Выйти из полноэкранного режима

Установленные зависимости включают следующее:

  • React-Bootstrap и «ванильный» Bootstrap для загрузки стилей CSS.
  • основной пакет AG Grid «community» и React Data Grid для рендеринга.

Чтобы запустить сервер разработки, используйте npm run dev.

Создание контейнера для карточек

Чтобы узнать, как интегрировать React-Bootstrap с AG Grid, вы создадите простое приложение со списком стран для посещения. Вы используете React-Bootstrap для добавления функциональности и визуального оформления сетки с помощью изображений и кнопок.

Внутри файла src/App.jsx вы инициализируете AG Grid вместе с React-Bootstrap. Начните с создания карточки Bootstrap для размещения сетки:

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;

Войти в полноэкранный режим Выход из полноэкранного режима

Используя компоненты Card и Stack, вы только что создали полноэкранную карточку с вертикально уложенным содержимым. Сетка будет размещена чуть ниже заголовка.

Чтобы отцентрировать карточку в теле, добавьте немного CSS в файл src/index.css:

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

Вход в полноэкранный режим Выйти из полноэкранного режима

После этих изменений карточка должна выглядеть следующим образом:

Создание базовой сетки AG

Чтобы добавить сетку в настройку, необходимо создать источник данных, что можно сделать с помощью хука useState():

// ...
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",
    },
  ]);

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

Войти в полноэкранный режим Выйти из полноэкранного режима

Каждая строка данных содержит название страны, URL-адрес соответствующего изображения Unsplash и булево значение, указывающее, была ли страна уже посещена. Кроме того, columnDefs определяет, как должны быть структурированы колонки сетки — например, их заголовки и ширина. В данном случае все колонки отображаются как текст, а колонка с изображением занимает оставшееся горизонтальное пространство с flex: 1.

Чтобы отобразить сетку, используйте компонент AgGridReact, передавая данные строки, определение столбца и любые дополнительные свойства — rowHeight в пикселях в данном случае — в качестве реквизитов:

// ...
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>
  );
};

// ...

Вход в полноэкранный режим Выход из полноэкранного режима

Сетка также поставляется с собственным CSS, который также необходимо импортировать. Класс ag-theme-material на обертке сетки указывает, какую тему использовать.

Теперь сетка готова, но она отображает все колонки как текст:

Давайте воспользуемся React-Bootstrap и заменим URL на изображения.

Отображение изображений

Чтобы отображать изображения в сетке, необходимо создать новый компонент, который будет использоваться в качестве рендеринга ячеек.

Создайте новый файл по адресу src/ImageRenderer.jsx со следующим содержимым:

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 получают данные о сетке и текущей ячейке в качестве реквизитов. Вы можете использовать props.getValue() для получения текущего значения ячейки, URL изображения в данном примере. Это значение затем передается компоненту React-Bootstrap Image вместе с другими реквизитами. Дополнительные имена классов Bootstrap и горизонтально выровненный Stack обеспечивают центрированное позиционирование и размер изображения с поправкой на сетку.

Чтобы использовать ImageRenderer в сетке, вернитесь к src/App.jsx и установите его как рендерер ячеек для колонки изображений:

// ...
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",
    },
  ]);
  // ...
};

// ...

Войти в полноэкранный режим Выход из полноэкранного режима

С этими улучшениями сетка уже выглядит намного лучше:

Добавление кнопок переключения

Помимо просмотра изображений, пользователь должен иметь возможность отмечать страны как посещенные. В настоящее время колонка посещенных стран пуста, так как содержит только булевы значения false. Чтобы показать кнопку переключения, создайте новый рендерер ячеек в 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;

Вход в полноэкранный режим Выход из полноэкранного режима

Используя ToggleButton от React-Bootstrap, вы можете легко создать флажок в стиле кнопки. Кнопка оформляется и маркируется в соответствии со значением реквизита, которое устанавливается при каждом переключении с помощью props.setValue().

Обратите особое внимание на реквизит id. Важно, чтобы он был уникальным, поскольку React-Bootstrap использует его как атрибут HTML id, соответствующий лежащему в основе <input> чекбоксу и стилизованному под кнопку <label>.

Теперь достаточно загрузить рендерер ячеек в src/App.jsx , и вы увидите, как в колонке появятся кнопки переключения:

// ...
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,
    },
  ]);
  // ...
};

// ...

Войти в полноэкранный режим Выход из полноэкранного режима

Настройка заголовка колонки

Одна из многих замечательных особенностей AG Grid заключается в том, что она очень легко настраивается, причем далеко не только с помощью пользовательских рендереров ячеек. Вы можете использовать эту настраиваемость вместе с React-Bootstrap для создания, например, пользовательских заголовков колонок с различными функциональными возможностями.

Настройка внешнего фильтра

В этом примере вы создадите пользовательский заголовок для столбца посещенных стран с возможностью фильтрации списка только по посещенным странам. Начните с добавления внешнего фильтра к сетке в 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>
  );
};

// ...

Вход в полноэкранный режим Выход из полноэкранного режима

В AG Grid внешние фильтры позволяют вам смешивать вашу пользовательскую логику фильтрации с механизмами, уже встроенными в грид. Чтобы включить их, необходимо предоставить два дополнительных реквизита:

В приведенном выше коде внешний фильтр управляется свойством состояния filterEnabled и функцией doesExternalFilterPass(), которая извлекает булево значение visited из данных строки для фильтрации грида.

Чтобы грид обрабатывал фильтр соответственно изменению filterEnabled, вы должны сначала сообщить ему об изменении конфигурации фильтра с помощью api.onFilterChanged().

Объект api доступен на элементе grid; поэтому сначала нужно использовать хук useRef() для создания ссылки на него. Затем, с помощью хука useEffect(), вызывайте api.onFilterChanged() каждый раз, когда filterEnabled изменяется.

Добавление заголовка кнопки переключения

Теперь, когда внешний фильтр готов, осталось создать пользовательский компонент заголовка, который будет устанавливать filterEnabled.

В src/VisitedHeader.jsx создайте следующий компонент:

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 снова использует ToggleButton из React-Bootstrap с пользовательским id и стилизацией на основе значений. Кроме того, у нее есть собственное свойство состояния checked для отслеживания состояния кнопки переключения. Родительский компонент уведомляется о каждом изменении с помощью методов useEffect() и setFilterEnabled(), передаваемых через props.

Вернувшись в файл src/App.jsx, вы должны установить компонент header и передать необходимый реквизит setFilterEnabled:

// ...
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,
    },
  ]);

  // ...
};

// ...

Вход в полноэкранный режим Выйти из полноэкранного режима

Стоит отметить, что AG Grid также предоставляет отдельное свойство headerComponentParams для передачи пользовательских реквизитов компоненту заголовка (помимо тех, что предоставляет grid). Сам компонент может быть установлен с помощью свойства headerComponent.

Конечный результат выглядит следующим образом:

Заключение

В этой статье вы узнали, как можно использовать AG Grid и React-Bootstrap вместе, а также насколько настраиваемым является AG Grid. Используя AG Grid в React Data Grid, вы получаете не только великолепный, очень продвинутый вид сетки, но и легкий доступ к экосистеме ведущего JS UI фреймворка. С такими мощными инструментами единственное ограничение для вашего приложения — это ваше воображение.

AG Grid — это ведущая JavaScript Grid. Он должен стать вашим основным инструментом с открытым исходным кодом, если вам нужно решение для создания сетки с батарейками, с расширенными возможностями, такими как потоковая передача данных, построение графиков, редактирование и многое другое. Ознакомьтесь с официальной документацией AG Grid, чтобы узнать больше.

Оцените статью
devanswers.ru
Добавить комментарий