Quando construímos interfaces com o Angular criamos componentes para cada uma das partes dessa interface, de forma que possamos aproveitá-los em outras partes da aplicação sem repetição de código. Essa prática aumenta a manutenibilidade do código e agiliza o desenvolvimento, uma vez que não precisamos criar essas partes do zero cada vez que eles aparecem.
Guia do artigo:
- Instalando e configurando o Angular Material
- Toolbar
- Menu
- Sidenav
- Icons
- Button
- Progress Bar
- Card
- List
- Tabs
Quando levamos a prática de componentização e reaproveitamento ao extremo chegamos a bibliotecas de componentes prontas. Essas bibliotecas fornecem elementos visuais e comportamentos padrão, que podemos importar para a nossa aplicação e utilizá-los, sem precisarmos nos preocuparmos com templates HTML e estilos CSS. No Universo Angular, uma das bibliotecas mais utilizadas é o Angular Material.
O Angular Material é a implementação oficial, para o Angular, do Material Design, a especificação de design para interfaces interativas do Google. O Material Design cobre desde pequenos elementos, como ícones e cores, até elementos maiores como navegação, cards, imagens e muito mais.
Nesse artigo, separamos os componentes do Angular Material em três categorias:
- Navegação
- Ícones, botões e indicadores
- Layout
Instalando e configurando o Angular Material
Para que possamos utilizar o Angular Material precisaremos, obviamente, de uma aplicação Angular. Precisaremos, também, de um ambiente de desenvolvimento Angular configurado. Caso você ainda não tenha experiência com o Angular, recomendo dar uma olhada no artigo de preparação do ambiente de desenvolvimento Angular e na série de primeiros passos no Angular:
Utilizando o npm, o gerenciador de pacotes do NodeJS, que instalamos no artigo de preparação do ambiente, instalaremos três pacotes: os componentes do Angular Material, o CDK e as animações da biblioteca.
Para instalar esses pacotes, basta executar o seguinte comando no diretório da aplicação:
npm install --save @angular/material @angular/cdk @angular/animations
Com os pacotes instalados, precisaremos importar o módulo de animações, utilizado internamente pelo Angular Material essencial para o funcionamento correto dos componentes, para dentro da nossa aplicação. Para isso, no arquivo app.modules.ts, basta adicionar o módulo de animações ao array de imports:
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
@NgModule({
...
imports: [
...
BrowserAnimationsModule
...
],
...
})
export class AppModule { }
Cada componente do Angular Material possui seu próprio módulo. Dessa forma, sempre que precisarmos utilizar um componente, precisaremos adicioná-lo ao array de imports do arquivo app.module.ts, como veremos mais adiante.
O próximo passo é adicionar um tema do Material Design à nossa aplicação. Isso pode ser feito através da importação do tema .css para dentro do arquivo styles.css da nossa aplicação. Atualmente, o Angular Material conta com quatro temas prontos:
- deeppurple-amber.css
- indigo-pink.css
- pink-bluegrey.css
- purple-green.css
Para um deles, no arquivo styles.css, adicionamos a seguinte linha ao topo do arquivo:
@import '@angular/material/prebuilt-themes/deeppurple-amber.css';
Alguns componentes, tais como mat-slide-toggle, mat-slider e matTooltip, dependem do Hammer.js, uma biblioteca JavaScript para a captura de gestos como cliques e toques, para funcionar. Basta instalá-lo utilizando o NPM:
npm install --save hammerjs
Por último, basta adicionar o pacote de ícones do Material Design. Para isso, adicione a importação do arquivo index.html da sua aplicação:
Componentes de navegação
O Angular Material fornece três componentes muito utilizados em qualquer aplicação: toolbar, menu e sidenav. O primeiro, toolbar, se trata de um contêiner para títulos, cabeçalhos e botões. O segundo, menu, permite a criação de menus e submenus dropdown. O último, sidenav, se trata de um menu lateral muito utilizado em interfaces responsivas e aplicativos mobile.
Toolbar
O componente toolbar permite agruparmos links, menus e títulos em uma barra de ferramentas, normalmente localizada no topo da aplicação:
O primeiro primeiro passo para utilizarmos o componente de toolbar é importar seu módulo para dentro do módulo da nossa aplicação, no arquivo app.module.ts:
import {MatToolbarModule} from '@angular/material/toolbar';
@NgModule({
...
imports: [
...
MatToolbarModule
...
],
...
})
export class AppModule { }
Feito isso, podemos utilizá-lo em qualquer template da aplicação através do seletor mat-toolbar:
<mat-toolbar>
<h1>Conteúdo do toolbar!</h1>
</mat-toolbar>
O componente permite alterar a paleta de cores do toolbar para primary, accent ou warn. A cor do fundo e do texto será escolhida de acordo com o tema que você escolheu para sua aplicação:
Para mudarmos a cor do toolbar, basta passar, para o atributo color, o nome da paleta de cores que desejamos utilizar:
<mat-toolbar color="primary">
<h1>Toolbar na cor <strong>primary</strong>!</h1>
</mat-toolbar>
<mat-toolbar color="accent">
<h1>Toolbar na cor <strong>primary</strong>!</h1>
</mat-toolbar>
<mat-toolbar color="warn">
<h1>Toolbar na cor <strong>primary</strong>!</h1>
</mat-toolbar>
Podemos, ainda, criar toolbars com múltiplas tuplas:
Para criarmos uma toolbar com múltiplas tuplas podemos utilizar outro componente, chamado mat-toolbar-row:
<mat-toolbar>
<mat-toolbar-row><strong>Primeira</strong> linha da toolbar.</mat-toolbar-row>
<mat-toolbar-row><strong>Segunda</strong> linha da toolbar.</mat-toolbar-row>
<mat-toolbar-row><strong>Terceira</strong> linha da toolbar.</mat-toolbar-row>
</mat-toolbar>
Menu
Com o componente Menu podemos criar menus do tipo dropdown com links e submenus. Em sua forma mais básica, um menu dropdown é composto de um botão que, ao ser clicado, abre uma aba com outros dois botões:
Para utilizar esse componente precisaremos, antes, importar seu módulo para dentro do módulo da aplicação:
import {MatMenuModule} from '@angular/material/menu;
@NgModule({
...
imports: [
...
MatMenuModule
...
],
...
})
export class AppModule { }
Criamos um template utilizando o componente mat-menu e o atribuímos a uma variável local chamada #meuMenu. No botão, utilizando a diretiva matMenuTriggerFor, indicamos qual template deve ser carregado quando o botão for clicado. No caso, o template meuMenu. O resultado, no navegador, será este:
<button [matMenuTriggerFor]="meuMenu">Menu</button>
<mat-menu #meuMenu="matMenu">
<button mat-menu-item>Item 1</button>
<button mat-menu-item>Item 2</button>
</mat-menu>
Podemos criar submenus para os botões do submenu, gerado um menu dropdown onde cada opção leva a outras opções:
Assim como no exemplo anterior, criamos templates para cada um dos submenus e os atribuímos a variáveis locais:
<button [matMenuTriggerFor]="menuComSubmenu"Mega menu</button>
<mat-menu #menuComSubmenu="matMenu">
<button mat-menu-item [matMenuTriggerFor]="submenu1">Submenu 1</button>
<button mat-menu-item [matMenuTriggerFor]="submenu2">Submenu 2</button>
</mat-menu>
<mat-menu #submenu1="matMenu">
<button mat-menu-item>Item 1</button>
<button mat-menu-item>Item 2</button>
</mat-menu>
<mat-menu #submenu2="matMenu">
<button mat-menu-item>Item 1</button>
<button mat-menu-item>Item 2</button>
<button mat-menu-item>Item 3</button>
<button mat-menu-item>Item 4</button>
</mat-menu>
Sidenav
Um dos elementos mais utilizados em aplicações que seguem o Material Design é a sidenav. Uma sidenav é uma barra lateral que pode agrupar menus, links ou qualquer outra informação útil para o usuário:
Para utilizarmos a sidenav, precisaremos importar seu módulo para dentro do módulo da aplicação:
import {MatSidenavModule} from '@angular/material/sidenav;
@NgModule({
...
imports: [
...
MatSidenavModule
...
],
...
})
export class AppModule { }
Em sua forma mais simples, a sidenav é composta da barra lateral fixa e uma área, também fixa, para o conteúdo da página, conforme visto na imagem figura 6. Para implementarmos essa sidenav, podemos utilizar o componente mat-sidenav-container, mat-sidenav, que receberá o conteúdo da sidenav e mat-sidenav-content, que receberá o conteúdo principal da página:
<mat-sidenav-container>
<mat-sidenav mode="side" opened>Conteúdo da sidenav</mat-sidenav>
<mat-sidenav-content>Conteúdo da página</mat-sidenav-content>
</mat-sidenav-container>
Normalmente, quando utilizamos uma sidebar, a mesma fica oculta até que o usuário clique em um botão ou realize qualquer outra ação:
Para que nossa sidenav fique naturalmente oculta e seja aberta apenas quando o usuário clicar em um botão, podemos criar uma variável local para a sidenav e executar o método toggle dessa variável quando um botão for clicado:
<mat-sidenav-container>
<mat-sidenav #variavelLocalSidenav mode="side">
Conteúdo da sidenav
</mat-sidenav>
<mat-sidenav-content>
<button (click)="variavelLocalSidenav.toggle()">
Toggle sidenav
</button>
</mat-sidenav-content>
</mat-sidenav-container>
Ícones, Botões e Indicadores
O Angular Material fornece componentes para botões dos mais diversos tipos, ícones, alertas e barras de carregamento.
Icons
O Angular Material fornece uma gama de ícones que podemos utilizar na nossa aplicação como simples componentes:
Para utilizar os ícones do Material Design na nossa aplicação precisaremos, antes, importar o módulo de ícones:
import {MatIconModule} from '@angular/material/icon;
@NgModule({
...
imports: [
...
MatIconModule
...
],
...
})
export class AppModule { }
Podemos utilizar os ícones através do componente mat-icon, passando para este o nome do ícone que desejamos utilizar:
<mat-icon>home</mat-icon>
Para conferir a lista completa de ícones basta acessar a página de ícones do Material Design.
Button
O elemento button, do HTML, pode ser estilizado com o Angular Material de forma a seguir os padrões do Material Design. Em sua forma mais básica temos um botão de fundo transparente e texto de cor que pode variar de acordo com o tema escolhido para a aplicação:
Para estilizar botões com o Angular Material precisaremos importar o módulo do mesmo para dentro do módulo da nossa aplicação:
import {MatButtonModule} from '@angular/material/button;
@NgModule({
...
imports: [
...
MatButtonModule
...
],
...
})
export class AppModule { }
Entretanto, diferentemente dos elementos que vimos até então, nós não utilizaremos componentes para estilizar os botões, mas sim diretivas. Diretivas são um recurso do Angular que permite modificarmos a aparência e atribuir comportamento a elementos HTML.
Para criar o botão que vimos na imagem figura 9, utilizaremos a diretiva mat-button:
<button mat-button>Básico</button>
<button mat-button color="primary">Primary</button>
<button mat-button color="accent">Accent</button>
<button mat-button color="warn">Warn</button>
<button mat-button disabled>Disabled</button>
Podemos criar, também, Raised Buttons, um tipo de botão que possui cor de fundo (de acordo com o tema escolhido) e sombra:
Para esse tipo de botão utilizaremos a diretiva mat-button:
<button mat-raised-button>Basic</button>
<button mat-raised-button color="primary">Primary</button>
<button mat-raised-button color="accent">Accent</button>
<button mat-raised-button color="warn">Warn</button>
<button mat-raised-button disabled>Disabled</button>
<a title="link" mat-raised-button routerLink=".">Link</a>
Existem diversos tipos de botões, como Flat Buttons, Stroked Buttons, Icon Buttons, Fab Buttons e Mini Fab Buttons:
A implementação dos outros tipos de botões é tão simples quanto as que já vimos:
<!-- Flat Buttons -->
<button mat-flat-button>Basic</button>
<button mat-flat-button color="primary">Primary</button>
<button mat-flat-button color="accent">Accent</button>
<button mat-flat-button color="warn">Warn</button>
<button mat-flat-button disabled>Disabled</button>
<a title="link" mat-flat-button routerLink=".">Link</a>
<!-- Stroked Buttons -->
<button mat-stroked-button>Basic</button>
<button mat-stroked-button color="primary">Primary</button>
<button mat-stroked-button color="accent">Accent</button>
<button mat-stroked-button color="warn">Warn</button>
<button mat-stroked-button disabled>Disabled</button>
<a title="link" mat-stroked-button routerLink=".">Link</a>
<!-- Icon Buttons -->
<button mat-icon-button>
<mat-icon>favorite</mat-icon>
</button>
<button mat-icon-button color="primary">
<mat-icon>favorite</mat-icon>
</button>
<button mat-icon-button color="accent">
<mat-icon>favorite</mat-icon>
</button>
<button mat-icon-button color="warn">
<mat-icon>favorite</mat-icon>
</button>
<button mat-icon-button disabled>
<mat-icon>favorite</mat-icon>
</button>
<!-- Fab Buttons -->
<button mat-fab>Basic</button>
<button mat-fab color="primary">Primary</button>
<button mat-fab color="accent">Accent</button>
<button mat-fab color="warn">Warn</button>
<button mat-fab disabled>Disabled</button>
<button mat-fab>
<mat-icon>favorite</mat-icon>
</button>
<a title="link" mat-fab routerLink=".">Link</a>
<!-- Fab Mini Buttons -->
<button mat-mini-fab>Basic</button>
<button mat-mini-fab color="primary">Primary</button>
<button mat-mini-fab color="accent">Accent</button>
<button mat-mini-fab color="warn">Warn</button>
<button mat-mini-fab disabled>Disabled</button>
<button mat-mini-fab>
<mat-icon>favorite</mat-icon>
</button>
<a title="link" mat-mini-fab routerLink=".">Link</a>
Badges
No Material Design, badges são pequenos selos onde podemos colocar informações adicionais referente ao texto, botão ou ícone:
Para utilizarmos badges precisaremos, antes, importar seu respectivo módulo:
import {MatBadgeModule} from '@angular/material/badge;
@NgModule({
...
imports: [
...
MatBadgeModule
...
],
...
})
export class AppModule { }
Badges, assim como buttons, não são componentes, mas sim diretivas. Para utilizá-los basta incluir a diretiva matBadge a um elemento HTML ou componente. Outras diretivas também estão disponíveis, tais como:
Diretiva |
Descrição |
matBadgeOverlap |
Indica se o badge deve ficar sobreposto ao item ou não. |
matBadgePosition |
Indica a posição do badge, podendo ser a combinação entre above ou below com before ou after. |
matBadgeColor |
A paleta de cores do badge, podendo ser primary, accent ou warn. |
MatBadgeSize |
Tamanho do badge, podendo ser small, medium ou large. |
matBadgeDescription |
Descrição aria-describedby do badge. |
Badges podem ser utilizados com diferentes elementos:
<!-- Texto com badge -->
<span matBadge="4" matBadgeOverlap="false">Texto com badge</span>
<!-- Button com badge -->
<button
mat-raised-button color="primary"
matBadge="8"
matBadgePosition="before|above"
matBadgeColor="accent"
matBadgeDescription="Badge com valor 8">
Clique!
</button>
<!-- Ícone com badge -->
<mat-icon matBadge="15" matBadgeColor="warn">home</mat-icon>
Progress Spinner Em algumas situações, as ações do usuário podem ocasionar um processamento longo ou mesmo uma requisição para o servidor. Nesses casos, para que indiquemos para o usuário que a aplicação está realizando a tarefa, podemos mostrar um progress spinner até que a tarefa seja finalizada:
Para adicionarmos Spinners a nossa aplicação, precisaremos importar seu respectivo módulo:
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner;
@NgModule({
...
imports: [
...
MatProgressSpinnerModule
...
],
...
})
export class AppModule { }
Para criar um Progress Spinner utilizamos o componente conhecido pelo nome mat-progress-spinner, passando como parâmetro um modo de execução, que pode ser indeterminate ou determinate.
O modo indeterminate irá gerar um spinner que circula infinitamente, como vimos na imagem figura 13, e pode ser implementado da seguinte forma:
<mat-progress-spinner mode="indeterminate"></mat-progress-spinner>
O modo determinate irá gerar um spinner que fixo em um determinado valor:
Esse valor, passado através do atributo value, deve estar entre 0 e 100:
<mat-progress-spinner mode="determinate" value="75"></mat-progress-spinner>
Progress Bar
Similar ao progress spinner, também podemos utilizar a progress bar para indicar pro usuário que uma tarefa está sendo executada:
Para utilizar a progress bar, precisaremos importar seu respectivo módulo para dentro da aplicação:
import {MatProgressBarModule} from '@angular/material/progress-bar;
@NgModule({
...
imports: [
...
MatProgressBarModule
...
],
...
})
export class AppModule { }
Da mesma forma que o progress spinner, a progress bar pode ser utilizada no modo indeterminate, onde o barra de progresso irá circular infinitamente, ou determinate, onde precisaremos determinar um valor de parada entre 0 e 100, através do atributo value. A implementação é similar ao progress spinner. Dessa vez, entretanto, utilizaremos o componente mat-progress-bar:
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
<mat-progress-bar mode="determinate" value="40"></mat-progress-bar>
Adicionalmente, a progress bar ainda possui um terceiro modo chamado buffer, onde é possível criar uma segunda linha. Esse tipo de barra de progresso é, normalmente, utilizada em player de vídeos: a barra principal indica o momento do vídeo que o usuário se encontra, a barra secundária indica o quanto do vídeo já foi baixado e a linha pontilhada o quanto ainda falta para ser baixado:
Nesse caso, além do atributo value, que representa a posição da barra principal, também precisaremos adicionar o atributo bufferValue, que representa a posição da barra secundária:
Layout
Componentes do tipo Layout são componentes utilizados, normalmente, para organizar o conteúdo da interface, de forma a facilitar a localização do conteúdo, títulos e menus. Dentre diversos componentes, os mais utilizados são Cards, Divider, Expansion Panel, List, Stepper e Tabs.
Card
Os cards do Material Design são amplamente utilizados para separar conteúdos distintos que apareçam em uma mesma tela:
Assim como outros componentes, para utilizar o Card, precisaremos importar seu respectivo módulo:
import {MatCardModule} from '@angular/material/card;
@NgModule({
...
imports: [
...
MatCardModule
...
],
...
})
export class AppModule { }
Em sua forma mais básica, um card é composto apenas de um fundo branco, uma sombra para destacá-lo e um conteúdo qualquer:
Esse resultado é obtido apenas utilizando o component mat-card:
<mat-card>Conteúdo do card!</mat-card>
Podemos adicionar título e subtítulo ao card, separando as informações através do tamanho e cor do texto:
Para isso, utilizamos outros componentes como mat-card-title, mat-card-subtitle e mat-card-content, em conjunto com o componente mat-card:
<mat-card>
<mat-card-title>Título do Card</mat-card-title>
<mat-card-subtitle>Subtítulo do Card</mat-card-subtitle>
<mat-card-content>Conteúdo do card!</mat-card-content>
</mat-card>
Podemos, ainda, adicionar botões abaixo do conteúdo do card:
Isso é feito através do componente mat-card-actions, onde podemos colocar qualquer tipo de botão:
<mat-card>
<mat-card-title>Título do Card</mat-card-title>
<mat-card-subtitle>Subtítulo do Card</mat-card-subtitle>
<mat-card-content>Conteúdo do card!</mat-card-content>
<mat-card-actions>
<button mat-button>BOTÃO 1</button>
<button mat-raised-button color="primary">BOTÃO 2</button>
</mat-card-actions>
</mat-card>
List
Listas são amplamente utilizadas em qualquer aplicação, e com o Material Design elas ganham uma aparência especial:
Para adicionarmos listas a nossa aplicação, precisaremos importar o módulo MatListModule para dentro da nossa aplicação:
import {MatListModule} from '@angular/material/list;
@NgModule({
...
imports: [
...
MatListModule
...
],
...
})
export class AppModule { }
A lista mais simples consiste de diversos itens, um abaixo do outro, sem muita estilização:
Essa lista é composta por dois componentes: mat-list, que agrupa os itens da lista, e um mat-list-item para cada item:
<mat-list>
<mat-list-item>Item 1</mat-list-item>
<mat-list-item>Item 2</mat-list-item>
<mat-list-item>Item 3</mat-list-item>
</mat-list>
No Material Design, listas podem possuir ícones:
Podemos utilizar a diretiva mat-list-icon no componente do ícone, e envolver o conteúdo do item com um elemento html qualquer, que receberá a diretiva mat-line:
<mat-list>
<mat-list-item>
<mat-icon mat-list-icon>home</mat-icon>
<p mat-line>Item com ícone 1</p>
</mat-list-item>
<mat-list-item>
<mat-icon mat-list-icon>cloud</mat-icon>
<p mat-line>Item com ícone 2</p>
</mat-list-item>
<mat-list-item>
<mat-icon mat-list-icon>favorite</mat-icon>
<p mat-line>Item com ícone 3</p>
</mat-list-item>
</mat-list>
Listas contam com divisores, que separam os itens da mesma:
Para adicionar divisores a lista, basta utilizar o componente mat-divider entre os itens da lista:
<mat-list>
<mat-list-item>
<p mat-line>Item com divisor 1</p>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<p mat-line>Item com divisor 2</p>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<p mat-line>Item com divisor 3</p>
</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
Expansion Panel
Expansion Panel permite escondermos informações até que o usuário clique para vê-las. Dessa forma, conseguimos construir interfaces mais limpas sem abrir mão de fornecer informações importantes ao usuário:
Para utilizarmos expansion panels, precisaremos importar seu respectivo módulo:
import {MatExpansionModule} from '@angular/material/expansion;
@NgModule({
...
imports: [
...
MatExpansionModule
...
],
...
})
export class AppModule { }
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
Nome do panel com ícone personalizado 1
</mat-panel-title>
<mat-panel-description>
Descrição!
</mat-panel-description>
</mat-expansion-panel-header>
<p>
Conteúdo do panel com ícone personalizado 1.
</p>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
Nome do panel com ícone personalizado 2
</mat-panel-title>
<mat-panel-description>
Outra descrição
</mat-panel-description>
</mat-expansion-panel-header>
<p>
Conteúdo do panel com ícone personalizado 2.
</p>
</mat-expansion-panel>
</mat-accordion>
Tabs
Tabs são amplamente para organizar o conteúdo em diferentes abas. Uma aba é escolhida para ser exibida para o usuário (normalmente a primeira) e as seguintes, para que o usuário possa visualizá-las, precisará clicar em seu respectivo link do menu:
Para utilizar o componente de tabs precisaremos, antes de tudo, importar seu respectivo módulo:
import {MatTabsModule} from '@angular/material/tabs;
@NgModule({
...
imports: [
...
MatTabsModule
...
],
...
})
export class AppModule { }
O elemento de tabs é um dos elementos mais simples e úteis do Material Design. Se trata apenas de um menu que provém acesso a diversas telas, com transição animada, como visto na imagem figura 28.
Para isso, utilizamos os componentes mat-tab-group, que agrupará todas as abas, e o componente mat-tab, que receberá um título (o nome que será usado no menu) e o conteúdo da página. Utilizaremos um componente mat-tab para cada aba:
<mat-tab-group>
<mat-tab label="Primeira">
<p>
Conteúdo 1
</p>
</mat-tab>
<mat-tab label="Segunda">
<p>
Conteúdo 2
</p>
</mat-tab>
<mat-tab label="Terceira">
<p>
Conteúdo 3
</p>
</mat-tab>
</mat-tab-group>
Conclusão
Exploramos alguns dos principais componentes do Material Design utilizando o Angular Material, a implementação do Material Design para o Angular. Vimos componentes para a construção de interfaces, agrupar conteúdo e navegação. Em um próximo artigo veremos como utilizar os componentes de formulário do Angular Material, de forma a deixar nossos formulários mais bonitos, intuitivos e dinâmicos.