Сортировка данных в таблице

Компонент таблицы DataTable в библиотеке Carbon Components Svelte предоставляет мощный и гибкий инструмент для отображения данных с возможностью сортировки по различным колонкам. Основной принцип работы сортировки основан на передаче функции sortRow и использовании состояния sortHeader.


Настройка таблицы с сортировкой

Для включения сортировки необходимо:

  1. Подключить компонент DataTable и его дочерние элементы:
<script>
  import { DataTable, Table, TableHead, TableBody, TableRow, TableHeader, TableCell } from "carbon-components-svelte";
  import { writable } from "svelte/store";

  const headers = [
    { key: "name", header: "Имя" },
    { key: "age", header: "Возраст" },
    { key: "department", header: "Отдел" }
  ];

  const rows = writable([
    { id: "1", name: "Иван", age: 28, department: "Разработка" },
    { id: "2", name: "Мария", age: 34, department: "Маркетинг" },
    { id: "3", name: "Сергей", age: 22, department: "Дизайн" }
  ]);

  let sortHeader = null;
  let sortDirection = "ASC";

  function sortRows(headerKey) {
    rows.update(currentRows => {
      const direction = sortHeader === headerKey && sortDirection === "ASC" ? "DESC" : "ASC";
      sortHeader = headerKey;
      sortDirection = direction;

      return [...currentRows].sort((a, b) => {
        if (a[headerKey] < b[headerKey]) return direction === "ASC" ? -1 : 1;
        if (a[headerKey] > b[headerKey]) return direction === "ASC" ? 1 : -1;
        return 0;
      });
    });
  }
</script>
  1. Настроить таблицу с возможностью сортировки через события:
<DataTable {rows} {headers}>
  <Table>
    <TableHead>
      <TableRow>
        {#each headers as header}
          <TableHeader
            on:click={() => sortRows(header.key)}
            sortDirection={sortHeader === header.key ? sortDirection.toLowerCase() : null}
          >
            {header.header}
          </TableHeader>
        {/each}
      </TableRow>
    </TableHead>
    <TableBody>
      {#each $rows as row}
        <TableRow>
          {#each headers as header}
            <TableCell>{row[header.key]}</TableCell>
          {/each}
        </TableRow>
      {/each}
    </TableBody>
  </Table>
</DataTable>

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

  • sortDirection принимает значения "ASC" или "DESC" и используется для визуального указания направления сортировки в заголовке колонки.
  • Функция sortRows проверяет текущий сортированный столбец и меняет направление сортировки при повторном клике на тот же заголовок.
  • Копия массива с помощью [...] гарантирует, что состояние rows будет обновлено корректно и сработают реактивные обновления Svelte.

Сортировка с пользовательской функцией

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

function customSort(headerKey, type = "string") {
  rows.update(currentRows => {
    const direction = sortHeader === headerKey && sortDirection === "ASC" ? "DESC" : "ASC";
    sortHeader = headerKey;
    sortDirection = direction;

    return [...currentRows].sort((a, b) => {
      let valA = a[headerKey];
      let valB = b[headerKey];

      if (type === "string") {
        valA = valA.toLowerCase();
        valB = valB.toLowerCase();
      }

      if (valA < valB) return direction === "ASC" ? -1 : 1;
      if (valA > valB) return direction === "ASC" ? 1 : -1;
      return 0;
    });
  });
}

Сортировка с использованием нескольких колонок

Для реализации многоуровневой сортировки (secondary sort) можно хранить массив сортировок:

let multiSort = [];

function sortMultiple(headerKey) {
  const existing = multiSort.findIndex(s => s.key === headerKey);
  if (existing >= 0) {
    multiSort[existing].direction = multiSort[existing].direction === "ASC" ? "DESC" : "ASC";
  } else {
    multiSort.push({ key: headerKey, direction: "ASC" });
  }

  rows.update(currentRows => {
    return [...currentRows].sort((a, b) => {
      for (let sort of multiSort) {
        if (a[sort.key] < b[sort.key]) return sort.direction === "ASC" ? -1 : 1;
        if (a[sort.key] > b[sort.key]) return sort.direction === "ASC" ? 1 : -1;
      }
      return 0;
    });
  });
}

Такой подход позволяет, например, сначала сортировать по отделу, а внутри отдела — по возрасту.


Интеграция с визуальными индикаторами

Для отображения стрелки направления сортировки в заголовке таблицы:

<TableHeader
  on:click={() => sortRows(header.key)}
  sortDirection={sortHeader === header.key ? sortDirection.toLowerCase() : null}
>
  {header.header}
  {#if sortHeader === header.key}
    <span>{sortDirection === "ASC" ? "↑" : "↓"}</span>
  {/if}
</TableHeader>

Это позволяет пользователю мгновенно увидеть, по какому столбцу и в каком направлении происходит сортировка.


Поддержка больших объемов данных

Для таблиц с большим количеством строк рекомендуется:

  • Использовать виртуализацию строк с помощью сторонних библиотек совместно с DataTable.
  • Реализовывать серверную сортировку, отправляя информацию о столбце и направлении сортировки на сервер и обновляя только отображаемые строки.
  • Сохранять состояние сортировки в Svelte store для корректного взаимодействия с пагинацией и фильтрацией.

Сортировка в Carbon Components Svelte строится на комбинации реактивного состояния, функций сортировки и визуальных индикаторов, что позволяет создавать гибкие и масштабируемые таблицы для сложных интерфейсов.