Angular IDPStrong Junior
Модулі / Грид / Анатомія таблиці
🔥 0

Модуль 5 · урок 1 з 10

Анатомія таблиці

Таблиця — найчастіша задача в ентерпрайзі й перше, що дають новому фронтендеру на робочому проєкті. Виглядає нудно, але саме тут одночасно вилазять типізація, продуктивність, реактивні фільтри й порожні стани. Почнемо з того, з чого таблиця складається.

Частини

панель інструментів пошук · фільтри · масові дії · експорт шапка назви колонок · сортування · чекбокс «вибрати всі» рядок · клік відкриває деталі рядок · чекбокс вибору рядок · дії наприкінці підвал пагінація · кількість знайдених · розмір сторінки
Чотири зони, і кожна повʼязана зі станом: панель задає фільтри, шапка — сортування, підвал — сторінку. Тіло лише показує результат.

Стан таблиці — це один обʼєкт

export interface TableState {
  page: number;
  size: number;
  sort: SortState[];          // масив — бо сортування багатоколонкове
  query: string;
  filters: Record<string, string>;
}

export interface SortState {
  key: string;
  dir: 'asc' | 'desc';
}

Це важлива думка, з якої варто почати модуль: сортування, фільтр і сторінка — це не три різні механізми, а один стан. Зміна будь-якої частини дає новий набір рядків. У сторі з модуля 4 це буде один BehaviorSubject<TableState> замість трьох.

// один потік замість трьох незалежних
readonly rows$ = combineLatest([this.allRows$, this.state$]).pipe(
  map(([rows, state]) => applyState(rows, state)),
);
Дрібниця, яку забувають усі

Коли змінюється фільтр, сторінку треба скинути на першу. Інакше користувач відфільтрував і бачить порожньо — бо він досі на сьомій сторінці, а результатів тепер два. Це найчастіший баг у гридах, і його не помічають, поки хтось не поскаржиться.

DataSource: посередник між даними й таблицею

В Angular Material таблиця не працює з масивом напряму. Вона працює з джерелом даних — обʼєктом, який уміє віддати потік рядків і прибрати за собою:

interface DataSource<T> {
  connect(): Observable<readonly T[]>;   // таблиця підписується при появі
  disconnect(): void;                    // і відписується при знищенні
}

Це дає дві переваги. По-перше, таблиця нічого не знає про те, звідки беруться дані — з масиву, з HTTP, з WebSocket. По-друге, підписка керується самою таблицею, тож витоків з уроку 10 модуля 4 тут не буває.

Найпростіший варіант — MatTableDataSource, готовий клас із вбудованими сортуванням, фільтром і пагінацією. Він зручний для швидкого старту, але має обмеження, про які поговоримо в наступному уроці.

Що саме просить лід

Ціль 5 з таблиці

Реалізувати насичену таблицю на Angular Material Table або AG-Grid: багатоколонкове сортування, клієнтська пагінація, динамічний пошук-фільтр і вибір рядків на строго типізованих моделях. Таблиця має плавно рендерити динамічні моковані потоки з повною типобезпекою, без лагів і витоків.

Розкладемо на пункти, кожному з яких присвячено окремий урок:

ВимогаУрокГоловна складність
Багатоколонкове сортування5Стабільний компаратор і пріоритет колонок
Клієнтська пагінація4Скидання сторінки при зміні фільтра
Динамічний пошук6Debounce, нормалізація рядка, кілька фільтрів разом
Вибір рядків7«Усі на сторінці» проти «усі взагалі»
Строга типізація8Колонка не може посилатись на неіснуюче поле
Без лагів9OnPush, track, відсутність роботи в шаблоні

≈ 30 хв · +25 XP за урок