Группировка опций

Группировка опций является важной функциональностью при работе с компонентами, которые предполагают выбор из списка значений, например Select, Autocomplete или Menu. В MUI библиотеке предусмотрены средства для создания визуально и семантически организованных списков, что повышает удобство использования интерфейсов и улучшает доступность.


Использование ListSubheader для группировки

Компонент ListSubheader позволяет создавать заголовки внутри списков. В контексте Select или Menu он помогает разделять элементы на логические группы.

import * as React from 'react';
import { Select, MenuItem, ListSubheader } from '@mui/material';

export default function GroupedSelect() {
  const [value, setValue] = React.useState('');

  const handleChange = (event) => {
    setValue(event.target.value);
  };

  return (
    <Sel ect value={value} onCha nge={handleChange}>
      <ListSubheader>Фрукты</ListSubheader>
      <MenuItem value="apple">Яблоко</MenuItem>
      <MenuItem value="banana">Банан</MenuItem>
      <ListSubheader>Овощи</ListSubheader>
      <MenuItem value="carrot">Морковь</MenuItem>
      <MenuItem value="broccoli">Брокколи</MenuItem>
    </Select>
  );
}

Ключевые моменты:

  • ListSubheader не является интерактивным элементом, поэтому на него нельзя кликнуть.
  • Его можно стилизовать через проп sx или классы для изменения цвета, отступов, шрифта.

Группировка в Autocomplete

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

import * as React fr om 'react';
import { Autocomplete, TextField } from '@mui/material';

const options = [
  { label: 'Яблоко', category: 'Фрукты' },
  { label: 'Банан', category: 'Фрукты' },
  { label: 'Морковь', category: 'Овощи' },
  { label: 'Брокколи', category: 'Овощи' },
];

export default function GroupedAutocomplete() {
  return (
    <Autocomplete
      options={options}
      groupBy={(option) => option.category}
      getOptionLabel={(option) => option.label}
      renderInput={(params) => <TextField {...params} label="Выберите продукт" />}
    />
  );
}

Примечания:

  • groupBy может возвращать любое строковое значение, позволяя динамически создавать группы.
  • В комбинации с renderGroup можно полностью контролировать отображение групп и их заголовков.

Кастомизация отображения групп

Свойство renderGroup предоставляет возможность кастомного рендеринга заголовков и элементов групп. Оно принимает объект { group, children } и должно возвращать JSX.

<Autocomplete
  options={options}
  groupBy={(option) => option.category}
  getOptionLabel={(option) => option.label}
  renderGroup={(params) => (
    <li key={params.key}>
      <strong style={{ fontSize: 16, color: '#1976d2' }}>{params.group}</strong>
      <ul>{params.children}</ul>
    </li>
  )}
  renderInput={(params) => <TextField {...params} label="Выберите продукт" />}
/>

Особенности кастомизации:

  • Можно изменять стиль заголовка групп, включая цвет, размер шрифта, отступы.
  • Внутри params.children находятся элементы группы (MenuItem по умолчанию), их тоже можно дополнительно обернуть или стилизовать.

Доступность и семантика

MUI автоматически заботится о корректной семантике для группированных списков:

  • Для Select и Menu ListSubheader получает атрибут aria-disabled="true".
  • Для Autocomplete группы создаются с корректной структурой списка и заголовков, что улучшает поддержку экранных читалок.

Практические советы по группировке

  1. Единая логика категорий: использовать однотипное значение для групп, чтобы избежать разрозненности и дублирования заголовков.
  2. Сортировка внутри групп: элементы внутри группы часто сортируются по алфавиту для удобства поиска.
  3. Стилизация: через sx или styled можно подчеркивать визуальное различие групп, например менять фон заголовка или добавлять отступы.
  4. Динамическая генерация: при получении данных с сервера можно автоматически создавать группы с помощью функций groupBy и renderGroup.

Пример комплексного компонента

import * as React from 'react';
import { Autocomplete, TextField } from '@mui/material';

const products = [
  { label: 'Яблоко', type: 'Фрукты' },
  { label: 'Банан', type: 'Фрукты' },
  { label: 'Морковь', type: 'Овощи' },
  { label: 'Брокколи', type: 'Овощи' },
  { label: 'Курица', type: 'Мясо' },
  { label: 'Говядина', type: 'Мясо' },
];

export default function ComplexGroupedAutocomplete() {
  return (
    <Autocomplete
      options={products}
      groupBy={(option) => option.type}
      getOptionLabel={(option) => option.label}
      renderGroup={(params) => (
        <li key={params.key}>
          <div style={{ background: '#f0f0f0', padding: '4px 8px', fontWeight: 'bold' }}>
            {params.group}
          </div>
          <ul style={{ margin: 0, padding: 0 }}>{params.children}</ul>
        </li>
      )}
      renderInput={(params) => <TextField {...params} label="Выберите продукт" />}
    />
  );
}

В этом примере реализована полноценная логическая структура: группы с фоном и внутренние элементы списка, что делает компонент удобным для взаимодействия и визуально понятным.


Группировка опций в MUI обеспечивает удобство работы с большими наборами данных, позволяет создавать логически организованные интерфейсы и поддерживает доступность для всех пользователей. Использование ListSubheader, groupBy и renderGroup предоставляет полный контроль над структурой и стилем групп.