Acerca de este codelab
1. Introducción
Escrito por el autor invitado Aayush Arora
Los elementos de Angular son componentes de Angular empaquetados como elementos personalizados. Son compatibles con Chrome, Opera y Safari, y se pueden usar en otros navegadores con polyfills. Pueden utilizar toda la infraestructura de Angular con la interfaz regular de Angular y la estrategia de detección de cambios. Una vez que se registran, estos elementos se pueden usar en el navegador.
Este codelab te servirá como guía para crear tu propio componente de deslizador de imágenes de Angular y, luego, te ayudará a transformarlo en un elemento de Angular a fin de que funcione fuera del framework de Angular.
Qué compilarás
En este codelab, compilarás un elemento de deslizador de imágenes con Angular Tu elemento podrá:
|
Qué aprenderás
- Cómo crear un componente personalizado de deslizador de imágenes
- Cómo transformar el componente personalizado de deslizador de imágenes en un elemento personalizado
- Cómo empaquetar el componente para que funcione dentro del navegador
Requisitos
- La versión más reciente de angular-cli
- El código de muestra
- Un editor de texto
- Conocimientos básicos de los componentes de Angular
Este codelab se enfoca en los elementos de Angular Los conceptos y los bloques de código que no son relevantes no se explican, pero se proporcionan para que los copies y pegues.
2. Cómo prepararte
Descarga el código
Haz clic en el siguiente vínculo para descargar el código de este codelab:
Descomprime el archivo ZIP descargado. Se descomprimirá una carpeta raíz (angular-element-codelab-master)
que contiene
dos carpetas: (image-slider)
y (image-slider-finished)
. Haremos toda nuestra edición de código en el directorio llamado image-slider.
Ejecuta el proyecto
Para ejecutar el proyecto, debes utilizar el comando ( ng-serve ) desde el directorio raíz ( control de imagen ).
Una vez que se inicialice la app, verás lo siguiente:
3. Crea un componente personalizado de deslizador de imágenes
¿Cómo crear un deslizador de imágenes?
Para este deslizador de imágenes, vincula los botones con el vínculo de clics de Angular. Crearemos un array de objetos con imágenes, etiquetas ALT, vínculos, etc. Colocaremos estas imágenes una debajo de la otra en un contenedor y traduciremos el contenedor cuando se haga clic en él.
Crearemos también un componente de deslizador de imágenes y lo transformaremos en un elemento de Angular.
- Contenedor para imágenes y títulos
- Un array que contiene los datos
- La plantilla para vincular los datos
4. Implementa el componente de deslizador de imágenes
Hay varias maneras de comenzar con cualquier proyecto, en este caso, para que tu proyecto sea lo más simple posible y concentrarte en los elementos de Angular, hemos proporcionado el código básico junto con los recursos CSS.
Crea un array y un servicio de datos
Recuerda que el sliderArray contiene lo siguiente:
- Una clave img para la URL de la imagen del deslizador
- Una etiqueta ALT para proporcionar alternativas para la imagen
- Un texto para proporcionar la descripción de la imagen
El archivo data.json
que ya está en el directorio src/assets
debe verse de la siguiente manera:
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'}
];
Necesitamos obtener estos datos en nuestro componente mediante un servicio. En el archivo data.service.ts
, escribiremos un método getData()
con el módulo httpClient
de @angular/common/http
, que recuperará los datos del array que creamos anteriormente.
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)
}
}
Recupera los datos del servicio de datos
Necesitamos importar nuestro servicio dentro del componente y, luego, suscribirnos al observable para obtener el objeto de data.json
Debemos realizar los tres pasos siguientes:
- Inicializar un array de componentes
- Suscribirse al observable que devuelve la función
getData()
- Crear un resultado de interfaz para la comprobación de tipos de datos después de suscribirse al observable
- Asignar los datos al array de componentes
Inicializa el array de componentes
Declararemos e inicializaremos el array de componentes dentro de slider.component.ts
, que es un vector de elementos:
Para declararlo:
sliderArray: object[];
Para inicializarlo:
constructor(private data: DataService) {
this.sliderArray = [];
}
A continuación, debemos importar e inicializar nuestro servicio dentro del constructor.
constructor(private data: DataService) {}
Ya estamos listos para usar nuestro servicio y llamar a nuestros métodos de servicios.
Obtén datos del servicio de datos
Para recibir los datos del servicio, llamaremos al método getData()
y nos suscribiremos al observable que devuelve. También crearemos una interfaz Result,
para comprobar que obtenemos los tipos de datos correctos.
Haremos esto dentro del método ngOnInit
:
this.data.getData().subscribe((result: Result)=>{
})
Asigna datos al array de componentes
Al final, asignaremos los datos al array de componentes:
this.data.getData().subscribe((result: Result)=>{
this.sliderArray = result.sliderArray;
})
Una vez que tenemos los datos dentro de nuestro array de componentes, podemos vincular nuestra plantilla con esos datos.
En slider.component.html,
, ya tenemos una plantilla HTML. El próximo paso es vincular esta plantilla con el sliderArray
.
5. Vincula los datos con la plantilla
Vincularemos los datos con la plantilla mediante la directiva *ngFor
y, por último, agregaremos transformaciones en la plantilla para que el deslizador funcione.
El proceso consiste en tres pasos:
- Vincular
sliderArray
a la plantilla - Agregar una vinculación de eventos para los botones del deslizador
- Agregar transformaciones CSS mediante
ngStyle
yngClass
Vincula slideArray al componente
Tenemos un contenedor que tiene un img-container
, text-container
y slider.
.
Vincularemos los datos de los tres contenedores usando la directiva *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>
Vincula eventos a slideArray
Una vez que se hayan vinculado los datos, enlazaremos el evento de clic con cada botón de deslizamiento a través de click binding
de Angular. Crearemos una función llamada selected(x)
, donde "x" es el índice del array.
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;
}
}
Cuestiones que debes tener en cuenta aquí:
- La función downselected reduce el valor de la propiedad transformación cincuenta veces el valor del índice que se pasó a la función al hacer clic en
selected
. - Esta lógica traduce el contenedor de texto a 100%, 50%, -50%, -100%, lo que da como resultado cuatro estados diferentes.
Agrega transformaciones de CSS con ngStyle y ngClass
Inicialmente, establecemos todas las imágenes con una opacidad cero. Luego, agregamos una clase selected
usando una ngClass directive
cuando el índice seleccionado es igual al índice de imagen. Esta clase selected
agrega una opacidad de "uno" a la imagen y la hace visible para el usuario.
<div class="img-container" *ngFor="let i of sliderArray; let select = index;"
[ngClass]="{'selected': select == selectedIndex}">
</div>
Después de esto, traduciremos el contenedor de texto según el valor transform
que se calculó mediante la función select()
.
<div [ngStyle]="{'transform': 'translateY('+ transform + '%' +')', 'transition': '.8s'}">
</div>
Después de realizar estos pasos, el código final se verá de la siguiente forma:
<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. Transforma el componente en un elemento de Angular
El procedimiento consta de cinco pasos:
- Utilizar
Shadow DOM
para el elemento de Angular - Hacer uso de
entryComponents
- Importar y usar el módulo
CreateCustomElement
de@angular/elements
- Definir nuestro
custom-element
- Ejecutar el método
ngDoBootstrap
Utiliza Shadow DOM para los elementos de Angular
Ahora que tenemos el deslizador de imágenes funcionando, solo necesitamos que sea un Angular Element
.
La parte divertida es que solo hay que hacer un pequeño cambio para que el componente DOM sea un Shadow DOM.
Necesitamos importar el módulo ViewEncapsulation
y utilizar el método ShadowDom
a partir de allí.
@Component({
selector: 'app-slider',
templateUrl: './slider.component.html',
styleUrls: ['./slider.component.css'],
encapsulation: ViewEncapsulation.ShadowDom
})
Utiliza entryComponents
El componente de entrada es un componente que Angular carga de manera imperativa. Debes especificar un componente de entrada, declarándolo dentro de un NgModule para el arranque inicial.
Aquí, especificaremos SliderComponent
en el array entryComponents
dentro de @NgModule
.
@NgModule({
declarations: [
SliderComponent
],
imports: [
BrowserModule,
HttpClientModule
]
})
Importa y utiliza el módulo createCustomElement
Aquí, debemos usar el módulo createCustomElement
de @angular/elements.
. Debes usar SliderComponent,
como parámetro para la función createCustomElement
. Luego, necesitamos registrar el slider
en el DOM.
import { createCustomElement } from '@angular/elements';
export class AppModule {
constructor(private injector: Injector) {
const slider = createCustomElement(SliderComponent, { injector });
}
}
Para registrar el deslizador como un elemento del DOM, lo definiremos con el método customElements.define
.
customElements.define('motley-slider', slider);
Por último, debemos inicializar este elemento personalizado con el método ngDoBootstrap()
. El código completo se verá de la siguiente forma:
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() {}
}
Empaqueta el elemento de Angular
Debemos modificar package.json
con nuestros nuevos comandos. Para ello, modificaremos el objeto de la secuencia de comandos dentro del archivo package.json
.
Veamos nuestro objeto de secuencia de comandos 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"
}
Ahora, podemos ejecutar el comando ng build & ng package
y, finalmente, ejecutaremos ng serve para entregar la carpeta dist/ carpeta que se generó con el comando de compilación. Además, podemos usar el gzip
que obtuvimos del comando ng package
, extraerlo y publicarlo como un npm module
.