Usando elementos de Angular – ¿Por qué y cómo? – Parte 1

Comenzando

Comencemos creando un nuevo proyecto de Angular en nuestro sistema. Para ello, asegúrate de tener la última versión de Angular CLI instalada. Ejecuta el siguiente comando en tu terminal:

$ npm install -g @angular/cli

Una vez completada esta instalación, podemos usarla para crear una nueva aplicación inicial en nuestro sistema así:

$ ng new angular-app

A continuación, se te pedirá que selecciones las características adicionales que quieras añadir a tu proyecto Angular, cosas como el enrutamiento y el tipo de formato de hoja de estilo. Selecciona la respuesta por defecto pulsando la tecla Enter/Return.

El CLI instala los paquetes y dependencias de Angular necesarias en una carpeta llamada angular-app. Puedes servir esta aplicación en el navegador ejecutando los siguientes comandos:

$ cd angular-app
$ ng serve --open
// --open flag will open the browser for you

Como puedes ver, la aplicación ya contiene algunas cosas que podemos mostrar en la pantalla. Pero no las necesitamos. Así que vuelve a tu editor de código (yo ❤️ VS Code) y borra todo lo que hay dentro del archivo src/app/app.component.html y escribe un único elemento <h1>.

<h1>Welcome To Angular Elements!</h1>

Si echas un vistazo a la estructura de archivos, verás que cada componente en angular consta de multitud de archivos. Sólo para el componente App, hay un archivo .ts, .html, .css, y un archivo spec.ts que contiene las pruebas, y un archivo module.ts. También habrá un archivo opcional routing.module.ts si hubieras elegido añadir la función de enrutamiento a la aplicación mientras la creabas usando el CLI.

En lugar de escribir todos estos archivos para nuestros componentes, Angular CLI nos da un método abreviado que generará estos archivos por nosotros. Usemos este método para crear un componente HelloWorld en nuestro sistema.

$ ng g c HelloWorld

Este único comando creará una carpeta llamada hello-world dentro de la carpeta app. Si abrimos esta carpeta, encontraremos estos 4 archivos dentro de ella:

  • hello-mundo.component.css
  • hello-mundo.component.html
  • hello-mundo.component.spec.ts
  • hello-mundo.component.ts

Sólo utilizaremos el archivo .html y .ts. Hay banderas adicionales que podemos pasar al comando ng g c. Pero para mantener las cosas simples y al punto, no las usaré. Revisa los Docs de Angular para saber más sobre cómo usar este comando.

Dentro del archivo hello-world.component.ts, verás que el selector está puesto en app-hello-world. Por lo tanto, si añades esto al app.component.html así:

<h1>Welcome To Angular Elements</h1>
<app-hello-world></app-hello-world>

Entonces el contenido de hello-world.component.html se mostrará en el navegador.

Nuestra configuración inicial ya está lista. Comencemos con el uso de los elementos de Angular.

Convertir un componente en elemento personalizado

Ahora mismo, tenemos un simple componente HelloWorld que simplemente imprime algún texto en la pantalla. Vamos a ver cómo podemos insertar este componente en la aplicación de una manera más dinámica. Para ello, vamos a sustituir el app-hello-world por un div y un button. Añadamos también el listener click al button, para que cuando alguien pulse el botón, se muestre el componente HelloWorld. Esto será manejado por una función showMessage(). Así que ir a la página app.component.html y hacer estos cambios:

<h1>Welcome To Angular Elements</h1>
<div></div>
<button (click)="showMessage()">Display?</button>

Luego tenemos que definir la función showMessage() en el archivo app.component.ts. Aquí utilizaremos la manipulación regular del DOM para obtener el div seleccionándolo mediante su id de hello. Luego, aplicaremos la función innerHTML para insertar el componente app-hello-world así:

export class AppComponent {
showMessage() {
const hello = document.getElementById('hello');
hello.innerHTML = '<app-hello-world></app-hello-world>';
}
}

Puedes ir a tu navegador y hacer clic en el botón, pero ya te digo que no va a pasar nada. Pero además, si vas a las herramientas de desarrollo del navegador y miras allí, verás que el componente HelloWorld está insertado.

La razón por la que no podemos ver el componente en la pantalla es que Angular no puede reconocer la etiqueta app-hello-world ya que se ha insertado en la plantilla de forma dinámica. Angular necesita que todos los elementos estén presentes en la plantilla, o necesita utilizar la fábrica de componentes dinámicos para instanciar el componente en tiempo de ejecución a través de su código.

Aquí es donde entra en juego Angular Elements. Al usar Angular Element, todo lo que necesitamos hacer es insertar la etiqueta dinámicamente, y el propio Angular instanciará el componente por nosotros. Vamos a ver por fin cómo utilizar este componente en nuestra app. En primer lugar, utiliza el comando ng add para instalar Angular Elements en nuestra app:

$ ng add @angular/elements

Una vez que tengas esto instalado, ve a app.module.ts y haz los siguientes cambios en el @NgModule:

import {NgModule, Injector} from '@angular/core';
import {createCustomeElement} from '@angular/elements';
@NgModule({
declarations: ,
imports: ,
entryComponents: ,
providers: ,
bootstrap:
})

Entonces, en la clase AppModule, escribe una función constructor crea una nueva instancia del createCustomElement y pásale el HelloWorldComponent como se muestra a continuación:

export class AppModule {
constructor(injector: Injector) {
const custom = createCustomElement(HelloWorldComponent, {injector: injector});
}
}

Junto con el componente, también tenemos que pasarle el injector. El injector es algo que utilizamos para resolver las dependencias. Con eso, hemos creado una instancia del HelloWorldComponent como elemento personalizado. Luego podemos utilizar la API customElements para definir la etiqueta del componente como app-hello-world.

customElements.define('app-hello-world', custom);

Vuelve al archivo hello-world.component.ts y elimina/comenta el selector dentro de la sección @Component. De esta forma, Angular no se confundirá y sabrá utilizar el elemento personalizado que acabamos de crear.

Realiza el comando ng serve --open para asegurarte de que Angular recoge todos los cambios que acabamos de realizar.

Es muy probable que el botón siga sin mostrar el HelloWorldComponent. Esto puede deberse a que Angular «falla al construir el HTMLElement». Para solucionar este problema, instala los polyfills webcomponentjs:

$ yarn add @webcomponents/webcomponentsjs

Luego, ve al archivo polyfills.ts e importa lo siguiente:

import '@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js';

¡Finalmente! Nuestro elemento personalizado se mostrará en la pantalla cuando pulsemos ese botón.