Aplicaciones fáciles con hyperHTML — 3

Ivan Torres
Easy apps with hyperHTML
5 min readAug 24, 2018

Mas acerca de componentes y manejo de estado

English Version

Parte 3 escrita por Ivan Torres y Paul Thompson.

Traducción por Lupita Hernandez e Ivan Torres

  1. Introducción, wire/bind
  2. Eventos y componentes
  3. Más acerca de componentes y manejo de estado simple
  4. Tipos de wires y definiciones personalizadas (intents)
  5. Custom elements con hyper
  6. Personalizando mis custom elements
  7. Corriendo pruebas!
  8. Carga asíncrona, placeholder y un Typeahead con hyper
  9. Manejando rutas
  10. Usando librerías externas (3rd party)

En la parte 2, usamos hyper Components para crear una tabla que se puede ordenar. Antes de añadir más cosas a nuestra tabla, vamos a ver el código que llevamos hasta ahorita.

Componentes de la tabla

Te diste cuenta que hay partes del código que podemos reusar? Si lo reestructuramos, podemos usar partes para otras tablas y ademas de que sera mas facil de mantener al solo tener que actualizar la parte necesaria en lugar de todo. Las siguientes partes son buenos candidatos para separar:

  • La definicion de la tabla en general
  • La cabecera (renglones y columnas)
  • El cuerpo de la tabla
  • El pie de la tabla… no tenemos uno pero se lo vamos a agregar nomas para divertirnos un poco

Veamos cómo podemos cambiar estas partes para tener un código que sea mas fácil de actualizar y reusar.

Tabla

Primero, vamos a crear el archivo Table.js y mover la mayoría del código aquí. No vamos a necesitar el uso de la función bind() en este archivo, en su lugar solo vamos a exportar la clase Table.

Después, vamos a actualizar index.js para importar nuestra tabla. Aquí es donde usaremos la función bind(). Recuerda que bind() funciona en nodos existentes como document.body. También date cuenta como estamos pasando la information a la clase Table: a través de un objecto en el constructor.

Cabecera

Nuestra clase Header también extenderá Component.

Primero ahí que mover el elemento <thead> de nuestra tabla a la función render(), así se vera render en Header:

En esta plantilla estamos escuchando el evento onclick en los elementos <th>. Como no queremos manejar el estado en esta clase, vamos a disparar un evento Custom llamado sort. Este evento va a tener algunos detalles como en cual columna esta el usuario ordenando y si es ascendente o descendiente.

Vamos a añadir una función update también. Al usar esta función, podemos estar seguros que siempre estamos usando los datos mas actuales. Si los datos cambian en el componente padre, nuestra cabecera va a recibir los nuevos datos. Esta se vera así:

Dispatch es una función incluida en Component. Va a crear un evento custom con su nombre basado en el primer parámetro, y los detalles de este basado en el segundo parámetro. Esta es una función muy util. Aprende mas acera de dispatch() en la documentación oficial (e ingles). Nuestra función onclick se ve ahora así:

Y así se ve nuestra clase Header:

Ahora vamos a actualizar la clase Table para cargar nuestro componente Header. Vamos a importarlo otra vez igual que antes. Después, en lugar de el elemento <thead> en la función render(), vamos a usar la clase Header:

${Header.for(this).update(this.state)}.

Component.for es una utilidad que te deja crear componentes directamente en render(). En lugar de crear el componente en alguna otra función, puedes crearlo aquí mismo. Header.for(object) va a enlazar la cabecera al objeto pasado, en este caso a nuestra clase Table, después llamamos la función update para actualizar la plantilla de la cabecera con el estado actual, esta sera pasado en cada llamado a render(). Vamos a usar otras formas de iniciar los componentes después. Lee mas sobre for() en la documentación.

Como ultimo paso, vamos a añadir la función onsort a la tabla para manejar el evento de ordenación: onsort="${this}". Esta función va a escuchar cuando el evento sort sea enviado por la cabecera. Necesitamos cambiar la función onclick a onsort, a la vez que la simplificaremos un poco. La información acerca de como ordenar los datos viene en el objeto dentro de la propiedad detail del evento. Con esto podemos ordenar los datos como antes y actualizar el estado de la tabla. Recuerda que estamos pasando el estado hacia la clase Header desde la clase Table.

Vamos a ver el código que llevamos hasta el momento:

Body

Para nuestro componente del cuerpo de la tabla, vamos a seguir los mismos pasos, mover el elemento tbody de la función render() de la clase Table a nuestro nuevo componente llamado Body. Body tendrá su propia función de render() de la siguiente forma:

Aunque es el componente que contiene la mayor información de nuestra tabla, es bastante compacto en cuanto a código, vamos a ver el archivo completo:

Pon atención a la linea:

this.props = props;

Vamos a usar esto para pasar los datos a nuestro componente Body. La información que pasemos sera la que usaremos en la plantilla.

Ahora, vamos a actualizar la clase Table para cargar el componente Body, usando import como antes.

import { Body } from './Body';

Para este componente, vamos a hacerlo un poco diferente. En lugar de usar Component.for, vamos a crear la instancia de este en el constructor. No necesitamos pasar datos en la creación.

this.body = new Body();

Con esto vamos a tener una tabla que funciona correctamente. Va a ordenarse, pero no estamos cambiando el arreglo (añadir o remover). Pero que tal si nuestros datos si cambian?. Podemos agregar la función update(props) en Body para recibir nuevos datos, justo como en Header.

De esta forma siempre vamos a recibir los datos mas actuales desde la clase Table. Ahora podemos llamar update() directamente:

this.body.update(this.data)

Vamos a ver todo el código hasta ahora:

Footer

Como lo prometido es deuda… vamos a agregar el pie de la tabla. Vamos a mostrar el numero total de columnas en este. Ademas de los elementos html para el tfoot, no hay nada nuevo en esta clase. Vamos a revisarla:

Como siempre vamos a actualizar la clase Table para cargar el componente Footer. Usaremos Component.for y la función update() para así siempre recibir los datos mas actuales, de otra forma nuestra cuenta no seria correcta.

Footer.for(this).update(this.data).

Yyyyy listo! Tenemos nuestra simple tabla con un manejo de estado simple: pasamos los datos hacia abajo y los eventos hacia arriba. Podríamos haber usado una librería para manejar el estado como Redux o Flux. Para nuestra tabla, realmente no necesitamos usar nada mas complejo que lo que tenemos.

Antes de ver la parte 4, exploremos una pequeña librería llamada ProppyJS. Esta no es una librería para el manejo de estado, pero si una librería que nos permite componer propiedades. De esta manera podemos componer las propiedades de varias fuentes y usarlas en cualquier componente. No estamos dando una gran libertad en nuestras aplicaciones, manteniendo separados las propiedades de los componentes. Con ProppyJS, podemos agregar un store Redux si así lo necesitamos después cuando el estado de nuestro componente se vuelva mas complejo.

Creamos una clase donde generamos las propiedades y la llamamos p, usándola en todos los componentes. Nuestro componente fue disminuido bastante y ahora la cabecera esta actualizando el ordenamiento directamente. Deja un comentario abajo si tienes preguntas sobre la implementación de ProppyJS en el código.

Queremos que estos tutoriales sean lo mejor que se puedan para ti! Si tienes retroalimentacion para nosotros, por favor déjalo en los comentarios. Gracias por leernos y sigue alerta a la siguiente parte donde exploraremos una característica poderosa llamada “intents”. Estos nos dejan expandir hyperHTML con definiciones personalizadas para nuestras plantillas.

--

--

Ivan Torres
Easy apps with hyperHTML

Multi-purpose Geek, Mobile/Web Developer, Father, mrpix, #nodejs