Sobre este codelab
1. Introdução
Escrito pelo autor convidado Aayush Arora
Os elementos Angular (link em inglês) são componentes do Angular empacotados como elementos personalizados. Atualmente, eles são compatíveis com o Chrome, Opera e Safari e estão disponíveis em outros navegadores pelo uso de polyfills. Esses elementos podem usar toda a infraestrutura do Angular com uma interface Angular comum e uma estratégia de detecção de mudanças. Depois de registrados, esses elementos podem ser usados no navegador.
Este codelab orientará a criação do seu próprio componente Angular de controle deslizante de imagem, além de ajudar você a transformá-lo em um elemento Angular para que ele funcione fora do framework Angular.
O que você criará
Neste codelab, você criará um elemento de controle deslizante de imagem usando o Angular. Seu elemento:
|
O que você aprenderá
- Como criar um componente personalizado de controle deslizante de imagem
- Como transformar o componente personalizado de controle deslizante de imagem em um elemento personalizado
- Como empacotar o componente para que ele funcione no navegador
O que é necessário
- Uma versão recente do angular-cli (link em inglês).
- O exemplo de código (link em inglês)
- Um editor de texto
- Conhecimentos básicos sobre os componentes do Angular
O foco deste codelab são os elementos Angular Conceitos e blocos de códigos sem relevância serão resumidos e apresentados para que você apenas os copie e cole.
2. Como começar
Fazer o download do código
Clique no link abaixo para fazer o download de todo o código para este codelab:
Descompacte o arquivo ZIP transferido por download. Isso descompactará uma pasta raiz (angular-element-codelab-master)
, que contém
duas pastas: (image-slider)
e (image-slider-finished)
. Faremos todo o nosso trabalho de codificação em um diretório denominado image-slider (controle deslizante de imagem).
Como executar o projeto
Para executar o projeto, execute o comando ng-serve pelo diretório raiz image-slider.
Depois que o app for inicializado, você verá esta janela:
3. Criar um componente personalizado de controle deslizante de imagem
Como criar um controle deslizante de imagem?
Para esse controle deslizante de imagem, você associará botões usando a vinculação de clique do Angular. Criaremos uma matriz de objetos contendo imagens, tags Alt, links etc. Colocaremos essas imagens uma abaixo da outra em um contêiner e o transformaremos quando houver um clique.
Criaremos um componente de controle deslizante de imagem e depois o transformaremos em um elemento Angular.
- Contêiner para imagens e títulos
- Uma matriz contendo os dados
- Modelo para vincular os dados
4. Implementar o componente do controle deslizante de imagem
Há diversas maneiras de começar um projeto. Neste caso, para manter nosso projeto o mais simples possível e para nos concentrarmos nos elementos Angular, fornecemos um código básico com CSS.
Como criar uma matriz e um serviço de dados
Lembre-se de que a matriz sliderArray terá:
- uma chave img para o URL da imagem no controle deslizante;
- uma tag Alt para fornecer um texto alternativo para a imagem;
- um texto para descrever a imagem.
O arquivo data.json
que já está no seu diretório src/assets
terá esta aparência:
sliderArray = [
{img: 'http://bloquo.cc/img/works/1.jpg', alt: '', text: '365 Days Of weddings a year'},
{img: 'http://bloquo.cc/img/works/2.jpg', alt: '', text: '365 Days Of weddings a year'},
{img: 'http://bloquo.cc/img/works/3.jpg', alt: '', text: '365 Days Of weddings a year'},
{img: 'http://bloquo.cc/img/works/4.jpg', alt: '', text: '365 Days Of weddings a year'},
{img: 'http://bloquo.cc/img/works/5.jpg', alt: '', text: '365 Days Of weddings a year'}
];
Precisamos buscar esses dados no nosso componente usando um serviço. No arquivo data.service.ts
, criaremos um método getData()
usando o módulo httpClient
de @angular/common/http
, que buscará os dados da matriz criada acima.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'
const URL = '../assets/data.json';
@Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) {}
getData() {
return this.http.get(URL)
}
}
Como buscar os dados no serviço de dados
Precisamos importar nosso serviço para dentro do componente e, em seguida, fazer a inscrição no observável para receber o objeto de data.json
Para isso, são necessárias três etapas:
- Inicializar uma matriz de componente
- Inscrever-se na classe observável retornada pela função
getData()
- Criar uma interface Result para conferir os tipos dos dados após a inscrição no observável
- Atribuir os dados à matriz de componente
Como inicializar a matriz de componente
Vamos declarar e inicializar a matriz de componente dentro de slider.component.ts
, que é uma matriz de objetos:
Para declarar:
sliderArray: object[];
Para inicializar:
constructor(private data: DataService) {
this.sliderArray = [];
}
Depois, precisamos importar e inicializar nosso serviço dentro do construtor
constructor(private data: DataService) {}
Agora, estamos prontos para usar nosso serviço e chamar os métodos dele.
Como buscar dados do serviço de dados
Para buscar os dados do serviço, chamaremos o método getData()
e faremos a inscrição no observável que ele retornará. Também criaremos uma interface Result,
para que possamos conferir se estamos recebendo o tipo correto de dados.
Faremos isso dentro do método ngOnInit
:
this.data.getData().subscribe((result: Result)=>{
})
Como atribuir dados à matriz de componente
No final, atribuiremos os dados à matriz de componente:
this.data.getData().subscribe((result: Result)=>{
this.sliderArray = result.sliderArray;
})
Depois de colocarmos os dados dentro da matriz do nosso componente, podemos vincular nosso modelo a esses dados.
Em slider.component.html,
, já temos um modelo de HTML. A próxima etapa é vincular esse modelo à sliderArray
.
5. Vincular os dados ao modelo
Vamos vincular os dados ao modelo usando a diretiva *ngFor
e, por fim, adicionar transformações no modelo para que o controle deslizante funcione.
Isso ocorre em três etapas:
- Vincular
sliderArray
ao modelo - Adicionar a vinculação de eventos para botões de controle deslizante
- Adicionar transformações CSS usando
ngStyle
engClass
Como vincular a slideArray ao componente
Temos um contêiner com um img-container
, um text-container
e um slider.
Vincularemos os dados nos três contêineres usando a diretiva *ngFor
.
<div class="container">
<div class="img-container" *ngFor="let i of sliderArray; let select = index;">
<img src="{{i.img}}" alt="{{i.alt}}" >
</div>
<div>
<div class="text-container">
<div class="page-text" *ngFor="let i of sliderArray;let select = index;">
<h3>{{i.text}}</h3>
</div>
</div>
</div>
</div>
<div class="slider">
<div class="slide-button-parent-container" *ngFor="let i of sliderArray; let x =index">
<div class="select-box">
<div class="slide-button">
</div>
</div>
</div>
</div>
Como vincular eventos à slideArray
Assim que os dados forem vinculados, nós vincularemos o evento de clique a cada botão deslizante usando o click binding
do Angular. Criaremos uma função chamada selected(x)
, em que x é o índice da matriz.
selected(x) {
this.downSelected(x);
this.selectedIndex = x;
}
downSelected(i) {
this.transform = 100 - (i) * 50;
this.selectedIndex = this.selectedIndex + 1;
if(this.selectedIndex > 4) {
this.selectedIndex = 0;
}
}
Pontos importantes:
- A função downselected diminui o valor da propriedade de transformação 50 vezes o valor do índice transmitido com o clique na função
selected
. - Essa lógica converte o contêiner de texto em 100%, 50%, -50% e -100%, resultando em quatro estados diferentes.
Como adicionar transformações CSS usando ngStyle e ngClass
Inicialmente, definimos todas as imagens com opacidade zero e adicionamos uma classe selected
usando a ngClass directive
quando o índice selecionado se torna igual ao índice da imagem. Essa classe selected
acrescenta uma opacidade de valor um à imagem, tornando-a visível para o usuário.
<div class="img-container" *ngFor="let i of sliderArray; let select = index;"
[ngClass]="{'selected': select == selectedIndex}">
</div>
Após isso, transformaremos o contêiner de texto de acordo com o valor de transform
calculado usando a função select()
.
<div [ngStyle]="{'transform': 'translateY('+ transform + '%' +')', 'transition': '.8s'}">
</div>
Depois de seguir todas essas etapas, você terá um código final semelhante ao mostrado abaixo:
<div class="container">
<div class="img-container" *ngFor="let i of sliderArray; let select = index;"
[ngClass]="{'selected': select == selectedIndex}">
<img src="{{i.img}}" alt="{{i.alt}}" >
</div>
<!--</div>-->
<div [ngStyle]="{'transform': 'translateY('+ transform + '%' +')', 'transition': '.8s'}">
<div class="text-container">
<div class="page-text" *ngFor="let i of sliderArray;let select = index;" [ngClass]="{'selected': select == selectedIndex}">
<h3>{{i.text}}</h3>
</div>
</div>
</div>
</div>
<div class="slider">
<div class="slide-button-parent-container" *ngFor="let i of sliderArray; let x =index" (click)="selected(x)" >
<div class="select-box">
<div class="slide-button" [ngClass]="{'slide-button-select': x == selectedIndex}" >
</div>
</div>
</div>
</div>
6. Transformar o componente no elemento Angular
Esse procedimento consiste em cinco etapas:
- Usar o
Shadow DOM
para um elemento Angular - Usar
entryComponents
- Importar e usar o módulo
CreateCustomElement
de@angular/elements
- Definir nosso
custom-element
- Executar o método
ngDoBootstrap
Como usar o shadow DOM para elementos Angular
Agora que temos o controle deslizante de imagem funcionando, só precisamos transformá-lo em um Angular Element
.
A parte boa é que apenas uma pequena mudança é necessária para transformar o DOM do componente em um shadow DOM.
Precisamos importar o módulo ViewEncapsulation
e usar o método ShadowDom
dele.
@Component({
selector: 'app-slider',
templateUrl: './slider.component.html',
styleUrls: ['./slider.component.css'],
encapsulation: ViewEncapsulation.ShadowDom
})
Como usar entryComponents
O componente de entrada é essencial no Angular. Para especificar um componente de entrada, inicialize-o em um NgModule.
Aqui, vamos especificar nosso SliderComponent
na matriz entryComponents
dentro de @NgModule
.
@NgModule({
declarations: [
SliderComponent
],
imports: [
BrowserModule,
HttpClientModule
]
})
Como importar e usar o módulo createCustomElement
Aqui, precisamos usar o módulo createCustomElement
de @angular/elements.
Você terá que usar o SliderComponent,
como um parâmetro para a função createCustomElement
. Depois, precisamos registrar o slider
no DOM.
import { createCustomElement } from '@angular/elements';
export class AppModule {
constructor(private injector: Injector) {
const slider = createCustomElement(SliderComponent, { injector });
}
}
Para registrar o controle deslizante como um elemento DOM, nós o definiremos usando o método customElements.define
.
customElements.define('motley-slider', slider);
Por fim, precisamos inicializar esse elemento personalizado usando o método ngDoBootstrap()
. O código completo terá esta aparência:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Injector } from '@angular/core';
import { createCustomElement } from '@angular/elements';
import { SliderComponent } from './slider/slider.component';
import { HttpClientModule} from "@angular/common/http";
@NgModule({
declarations: [
SliderComponent
],
imports: [
BrowserModule,
HttpClientModule
]
})
export class AppModule {
constructor(private injector: Injector) {
const slider = createCustomElement(SliderComponent, { injector });
customElements.define('motley-slider', slider);
}
ngDoBootstrap() {}
}
Como empacotar o elemento Angular
Será necessário modificar o package.json
com nossos novos comandos. Modificaremos o objeto script no arquivo package.json
.
Vamos conferir nosso objeto script modificado:
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod --output-hashing=none",
"package": "cat dist/my-app/{runtime,polyfills,scripts,main}.js | gzip > elements.js.gz",
"serve": "http-server",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
}
Agora, podemos executar o comando ng build & ng package
e, por fim, executar ng-serve para exibir a pasta dist/ gerada usando o comando de compilação. Além disso, podemos usar o gzip
recebido com o comando ng package
, extraí-lo e publicá-lo como um npm module
.