Создание лейаутов и сеток с помощью Angular CDK и Angular Material

Aleksandr Serenko
F.A.F.N.U.R
Published in
5 min readFeb 14, 2022
Создание лейаутов и сеток с помощью Angular CDK и Angular Material

В данной статье приведу пример решения с использованием размеров и устройств, которые предлагает Angular CDK.

В результате получим следующее:

Одним из минусов документации по Angular Material является отсутствие примеров работы с Angular CDK. В результате чего, некоторые разработчики начинают изобретать собственные решения для создания сеток и лейаутов, хотя все это можно реализовать средствами Angular CDK.

Ранее я уже писал о реализации колонок как в BootstrapBanx. Создание базового лейаута в Angular, а также использовал данное решение в цикле статей про тестовое задание — Тестовое задание на Angular. Создание UI kit для приложения.

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

Установка

Для работы ниже описанных методов необходим Angular приложение с добавленным пакетом Angular Material.

Для создания проекта можно использовать следующую команду:

ng new my project

Для добавления material нужно выполнить команду:

ng add @angular/material

Отмечу, что пакеты нужно добавлять именно с помощью angular-cli или nx, так после установки пакета необходимо сконфигурировать тему. Все это зашито в скриптах, которые выполнятся сами, если добавлять пакет через angular-cli, а не с помощью yarn или npm.

Обзор Layouts

В документации по CDK есть отличный раздел, в котором приведены примеры обработки media запросов CSS — Layouts.

В данном случае имеется следующая таблица:

CDK представляет следующий объект:

Это позволяет реализовывать макеты для 3 платформ, с двумя состояниями (portrait, lanscape):

  • Мобильные устройства — Handset
  • Планшеты — Tablet
  • ПК — Web

Для современной веб-разработки это более чем достаточно, но нет никаких проблем добавить еще несколько платформ и состояний.

Также вместе с Breakpoints, CDK предоставляет сервис для отслеживания изменений размера экрана, для определения текущего размера — BreakpointObserver.

Пример использования сервиса из документации:

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

Создание макета с отслеживанием изменения платформы

Для создания макета с изменением платформы создадим новый модуль и компонент:

ng g m layout
ng g c layout

Если использовать Nx, тогда можно все это вынести в отдельную либу и команды будут следующими:

nx g lib ui/layout 
nx g c layout --project=ui-layout

Так как тип платформы может понадобиться не только в компоненте layout’а, создадим сервис LayoutService:

Как видно из реализации, идет подписка на все виды платформ, а затем все состояния объединяются и возвращается базовая платформа с помощью соответствия типу:

export const LAYOUT_SHORT_TYPES_MAP = {
[Breakpoints.Handset]: Breakpoints.Handset,
[Breakpoints.HandsetPortrait]: Breakpoints.Handset,
[Breakpoints.HandsetLandscape]: Breakpoints.Handset,
[Breakpoints.Tablet]: Breakpoints.Tablet,
[Breakpoints.TabletPortrait]: Breakpoints.Tablet,
[Breakpoints.TabletLandscape]: Breakpoints.Tablet,
[Breakpoints.Web]: Breakpoints.Web,
[Breakpoints.WebPortrait]: Breakpoints.Web,
[Breakpoints.WebLandscape]: Breakpoints.Web,
};

Где в подписке идет сопоставление типу:

type = LAYOUT_SHORT_TYPES_MAP[query];

Если нужно различать состояния, то нужно просто приравнивать найденный тип:

type = query;

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

Создадим макет с 3 вариантами отображения:

Создание лейаутов и сеток с помощью Angular CDK и Angular Material

Добавим соответствующую логику в LayoutComponent:

В самом компоненте добавим ранее созданный сервис и подпишемся на изменения размера экрана:

export class LayoutComponent implements OnInit {
readonly breakpoints = Breakpoints;

layoutType$!: Observable<string>;

constructor(private readonly layoutService: LayoutService) {}

ngOnInit(): void {
this.layoutType$ = this.layoutService.layoutType$;
}
}

В html добавим отображение компонентов для соответствующего типа экрана:

<ng-container [ngSwitch]="layoutType$ | async">
<ng-container *ngSwitchCase="breakpoints.Web">
<banshop-header></banshop-header>
<main class="web" automation-id="web">
<banshop-container>
<router-outlet></router-outlet>
</banshop-container>
</main>
<banshop-footer></banshop-footer>
</ng-container>
<ng-container *ngSwitchCase="breakpoints.Tablet">
<banshop-sidebar></banshop-sidebar>
<main class="tablet" automation-id="tablet">
<banshop-container mode="fluid">
<router-outlet></router-outlet>
</banshop-container>
</main>
</ng-container>
<ng-container *ngSwitchDefault>
<div>
<banshop-header></banshop-header>
<main class="handset" automation-id="handset">
<banshop-container mode="fluid">
<router-outlet></router-outlet>
</banshop-container>
</main>
</div>
<banshop-menu></banshop-menu>
</ng-container>
</ng-container>

Из примера видно, что в макете реализованы три варианта.

Примеры всех используемых компонентов я приводить не буду. Компоненты можно посмотреть в репозитории banshop.

Последним важным нюансом является реакция на смену экрана. И если с точки зрения JS есть подписка, то для того чтобы CSS знал о используемых размерах, можно создать несколько mixin’ов для упрощения верстки:

Если посмотреть миксины, то там просто обертка над таблицей размеров в Angular CDK.

Пример использования миксинов есть в layout.component.scss:

@use 'libs/ui/stylesheets/mixins' as store-mixins;

:host {
display: flex;
min-height: 100%;
flex-direction: column;
width: 100%;

@include store-mixins.media-tablet() {
flex-direction: row;
}

@include store-mixins.media-web() {
flex-direction: column;
}
}

В данном случае, при изменении расширения будут применяться стили либо для handset, либо для tablet или web.

Так как используется принцип mobile first, стили размещены от меньшего расширения к большему.

Если запустить проект, то получим следующее:

Резюме

В данной статье рассмотрели представленные варианты размеров из Angular CDK:

  • handset — мобильное устройство
  • tablet — планшет
  • web — пк

Для определения типа устройства, добавили глобальный сервис LayoutService, который с помощью BreakpointObserver наблюдает за сменой экрана.

При изменении экрана в html макете реализовали смену отображения компонентов в зависимости от текущего устройства.

Ссылки

Все исходники находятся на github, в репозитории:

Для того, чтобы посмотреть состояние проекта на момент написания статьи, нужно выбрать соответствующий тег — layouts.

Подписывайтесь на блог, чтобы не пропустить новые статьи про Angular, и веб-разработку. Medium | Telegram| VK | FB | Tw | Inst | Ln

--

--

Aleksandr Serenko
F.A.F.N.U.R

Senior Front-end Developer, Angular evangelist, Nx apologist, NodeJS warlock