Angular CDK Layout - как удобный помощник при разработке адаптивных Angular приложений

В процессе разработки адаптивных UI многие разработчики сталкиваются с ситуациями, когда нужно понимать с каким размером окна в текущий момент работает ваш Angular SPA (Single Page Application) для того чтобы соответственно реагировать или изменять пользовательский интерфейс.

Angular Material CDK - предлагает пакет Layout который позволит вам получить текущую информацию о размере окна, а также подписываться на его изменения.

В состав пакета CDK Layout входят сервисы которые позволяют определить размер окна сопоставимо с медиа запросами в css.

Как использовать модуль CDK Layout :

Первым делом вы должны установить Angular Material CDK в ваше Angular приложение:

npm install @angular/cdk // или yarn add @angular/cdk

Затем импортируйте LayoutModule и добавьте его в imports вашего NgModule

import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { LayoutModule } from ‘@angular/cdk/layout'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, LayoutModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }

Теперь вы можете использовать сервисы CDK Layout в ваших компонентах.

Подробно о функционале который предлагает модуль Layout :

1. BreakpointObserver

BreakpointObserver - это сервис в котором существует два метода observe и isMatched

BreakpointObserver.isMatched - является методом который возвращает boolean значение и в который нужно передать в виде аргумента медиа запрос или массив медиа запросов.

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

import {Component, OnInit} from '@angular/core'; import {BreakpointObserver} from '@angular/cdk/layout'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { constructor(public breakpointObserver: BreakpointObserver) { } ngOnInit() { if (this.breakpointObserver.isMatched(['(max-width: 400px)', '(min-width: 900px)'])) { console.log('isMatched'); } } }

В темплейте:

<div *ngIf="breakpointObserver.isMatched(['(min-width: 900px)'])"> <h1>isMatched</h1> </div>

В примере выше в компоненте - мы увидим в консоли надпись isMatched в том случае если при инициализации компонента при событии ngOnInit, любой из css медиа запросов в массиве будет удовлетворен.

Во втором примере в темплейте - мы увидим блок div только в том случае если ширина окна будет больше чем 900px.

BreakpointObserver.observe :

Метод observe возвращает observable типа BreakpointState на который мы можем подписаться и получать информацию об изменении размеров окна в соответствии с заданным медиа запросом или массивом медиа запросов.

import {Component, OnInit} from '@angular/core'; import {BreakpointObserver, BreakpointState} from '@angular/cdk/layout'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { constructor(public breakpointObserver: BreakpointObserver) { } ngOnInit() { this.breakpointObserver .observe(['(min-width: 960px)']) .subscribe((state: BreakpointState) => { if (state.matches) { console.log('Viewport is 960px or over!'); } else { console.log('Viewport is getting smaller!'); } }); } }

В примере выше мы будем видеть в консоли сообщения если экран пользователя будет становиться больше или меньше 960px.

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

export interface BreakpointState { matches: boolean; breakpoints: { [key: string]: boolean; }; }

Из этого можно сделать вывод, что поле matches будет true - если хотя бы один из переданных медиа запросов будет удовлетворен. Соответственно если мы хотим получать информацию только по конкретному переданному медиа запросу - мы можем сделать так:

ngOnInit() { this.breakpointObserver .observe(['(min-width: 960px)', '(min-width: 1060px)']) .subscribe((state: BreakpointState) => { if (state.breakpoints['(min-width: 1060px)']) { console.log('Viewport is 1060px or over!'); } }); }

Дополнительно мы можем использовать объект Breakpoints, в котором уже есть фиксированные брейкпоинты в соответствии со спецификацией Google's Material Design

import {Component, OnInit} from '@angular/core'; import {BreakpointObserver, Breakpoints, BreakpointState} from '@angular/cdk/layout'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { constructor(public breakpointObserver: BreakpointObserver) { } ngOnInit() { this.breakpointObserver .observe([Breakpoints.TabletPortrait]) .subscribe((state: BreakpointState) => { if (state.matches) { console.log('Viewport is TabletPortrait!'); } }); } }

2. MediaMatcher

MediaMatcher - это сервис, который является оберткой над нативным методом JavaScript matchMedia. Его можно использовать так же как и BreakpointObserver.observe для наблюдения за изменением размера окна в зависимости от заданного медиа запроса.

import {Component, OnDestroy, OnInit} from '@angular/core'; import {MediaMatcher} from '@angular/cdk/layout'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit, OnDestroy { matcher: MediaQueryList; constructor(public mediaMatcher: MediaMatcher) { } ngOnInit() { this.matcher = this.mediaMatcher.matchMedia('(min-width: 960px)'); this.matcher.addListener(this.myListener); } myListener(event) { if (event.matches) { console.log('match'); } else { console.log('no match'); } } ngOnDestroy() { this.matcher.removeListener(this.myListener); } }

Разница между BreakpointObserver.observe и MediaMatcher заключается в том что MediaMatcher предоставляет вам доступ к нативному JS объекту MatchQueryList, в некоторых случаях это может быть полезно.

Теперь, я надеюсь у вас есть полное понимание как пользоваться Angular CDK Layout для создания своих адаптивных Angular UI. =)

0
Комментарии
-3 комментариев
Раскрывать всегда