Construyo un Kanban Board en Vanilla JavaScript, React, Angular y Flutter — Parte 1

Thian Lopez Zambrano
10 min readMar 15, 2023

--

Kanban board Vanilla JavaScript

En esta serie de stories te voy a compartir como hacer una sencilla app web, vamos hacer un sencillo Kanban Board y replicarlo en diferentes tecnologías: Vanilla JavaScript, React, Angular y Flutter, con el fin de poder realizar una comparativa entre esta pequeña variedad de “sabores” que tenemos para desarrollar aplicaciones web.

¿Por qué estas tecnologías?

Vanilla JavaScript, React, Angular y Flutter son las tecnologías de la que estaré hablando en su mayoría, como divulgador de contenidos de programación y desarrollo, así que muy atentos con lo que se viene.

¿Y por qué un sencillo Kanban board?

Un Kanban Board puede ser muy sencillo si eres un desarrollador con algunos años de experiencia, sin embargo la idea es mantener las cosas sencillas lo más que podamos, además, de que esta “sencilla” aplicación supone que podamos puntualizar en muchos conceptos claves a la hora de desarrollar una web, tales como: manejo de estilos y vistas, renderizado, manejo de estados, data binding, eventos, ciclos de vida de una aplicación, etc.

Vanilla JavaScript

Comencemos por la forma más básica de hacer una web. Vanilla JavaScript es una iniciativa que pretende mostrarnos las ventajas de usar JavaScript puro, es decir, sin la intervención de framework alguno. Una ventaja de JavaScript puro es que no vamos a necesitar de librerías pesadas para lograr nuestro cometido, por lo contrario, los llamados “frameworks” se valen de muchas otras librerías para poder funcionar, otra ventaja es la no dependencia de librerías de este tipo (frameworks), ¿Recuerdan lo que fue pasar de AngularJs a Angular 2+ o migrar desde JQuery?.

Antes de comenzar

Para el desarrollo de nuestro proyecto usaremos Tailwindcss que es un framework de CSS que nos va a ahorrar mucho tiempo al poder usar sus estilos a través de las clases pre-definidas en el framework; y para seguir manteniendo las cosas simples, vamos a usar esta tecnología a través de su CDN.

Ahora si, manos a la obra

Comencemos por crear la carpeta vacía con el nombre de nuestro proyecto (yo lo llamare vanillajs-kanban), en el directorio de nuestro computador que creamos conveniente, luego abrimos la carpeta con tu editor de texto favorito, en mi caso para todo el tutorial usaré Visual Studio Code.

Lo primero que debemos hacer es crear un archivo llamado index.html y comenzamos por escribir dentro de él, la sintaxis básica para tener una página web HTML5.

Primero lo primero

Antes de comenzar a maquetar o comenzar a programar como tal, configuremos nuestro archivo con el fin de cargar los estilos CSS que nos provee Tailwindcss, para esto a agregamos la siguiente etiqueta (script) entre las etiquetas head:

<!-- ... -->
<head>
<!-- ... -->
<script src="https://cdn.tailwindcss.com"></script>
</head>
<!-- ... -->

Esto será suficiente para poder usar las clases que nos provee Tailwindcss.

A maquetar nuestro HTML

Comencemos por maquetar nuestro HTML, primero vamos a formar las 3 columnas en donde enlistaremos nuestras tareas según el estado en el que se encuentren: To do, Doing y Done. Dentro de nuestra etiqueta Body ubiquemos el siguiente código:

<!-- ... -->
<body>
<div class="container">
<div class="columns-3 h-screen p-2">
<div class="columns-1 h-full rounded border-2 border-teal-500 p-2">
<h1 class="my-2 text-xl">To do</h1>
<div id="todoContainer">
<!-- Aqui vamos a agregar de manera dinamica el codigo HTML de nuestras tareas -->
</div>
</div>
<div class="columns-1 h-full rounded border-2 border-yellow-500 p-2">
<h1 class="my-2 text-xl">Doing</h1>
<div id="doingContainer">
<!-- Aqui vamos a agregar de manera dinamica el codigo HTML de nuestras tareas -->
</div>
</div>
<div class="columns-1 h-full rounded border-2 border-rose-500 p-2">
<h1 class="my-2 text-xl">Done</h1>
<div id="doneContainer">
<!-- Aqui vamos a agregar de manera dinamica el codigo HTML de nuestras tareas -->
</div>
</div>
</div>
</div>
</body>
<!-- ... -->

Notemos que en cada columna hemos ubicado primero un título (To do, Doing, Done) a través de una etiqueta h1 y luego un div vacío, la idea es tomar la referencia de este div con el fin de manipular su contenido desde JavaScript, aquí ubicaremos el código HTML que contenga las tareas dependiendo de su estado, en otras palabras es aquí es donde vamos a renderizar nuestras tareas dependiendo de su estado.

Esto deberá mostrarnos lo siguiente:

Creamos el formulario para ingresar una nueva tarea

Para ingresar nuestras tareas vamos a maquetar un pequeño formulario, uno muy simple que tendrá solo un input de tipo text a través del cual vamos a ingresar una pequeña descripción de nuestra tarea y también un botón a través de la etiqueta button con el cual dispararemos el evento onsubmit de nuestro formulario, ubicaremos nuestras etiquetas dentro de la “columna To do” entre el título y el contenedor que reservamos para renderizar nuestras tareas.

<!-- ... -->
<div class="columns-1 h-full rounded border-2 border-teal-500 p-2">
<h1 class="my-2 text-xl">To do</h1>
<!-- Formulario de ingreso de nueva tarea -->
<div class="columns-1 p-1 h-fit rounded border-2 border-teal-500 mb-3 p-3">
<form id="nuevaTareaFormulario" onsubmit="agregarNuevaTarea(event)">
<input type="text" id="descripcionNuevaTarea" class="rounded w-full border-2 border-b-gray-500 p-1.5" placeholder="Descripcion de la tarea" />
<button type="submit" class="bg-teal-600 rounded border-3 border-gray-500 text-white text-center w-full my-1 p-1">
Guardar nueva tarea
</button>
</form>
</div>
<!-- Fin formulario de ingreso de nueva tarea -->
<div id="todoContainer">
<!-- Aqui vamos a agregar de manera dinamica el codigo HTML de nuestras tareas -->
</div>
</div>
<!-- ... -->

Si me has seguido bien hasta aquí, tu aplicación debería verse de la siguiente forma:

Volvamos al código anterior

Vamos a puntualizar ciertos detalles acerca del código que agregamos, comencemos por nuestra etiqueta form, en la que hemos especificado el atributo onsubmit en el cual configuramos la función que debemos invocar una vez nuestro usuario envié el formulario, la función que invocaremos será la función agregarNuevaTarea y como argumento vamos a enviar la información de nuestro “evento” como tal, esta función será programada más adelante.

Luego en la etiqueta input vamos a destacar lo siguiente: id="descripcionNuevaTarea" con esto nos aseguramos un identificador único que nos va a servir mucho para poder manipular la información especificada a través de esta caja de texto.

Por último destaquemos nuestra etiqueta button cuya parte más importante reside en el atributo type en el cual especificamos que este botón es de tipo submit, es decir, le decimos al formulario que cuando este botón sea presionado, deberá disparar el evento onsubmit configurado en la etiqueta form.

Comencemos a programar

Una vez terminada nuestra fase de maquetación vamos a programar nuestro código en JavaScript. Para empezar a escribir nuestro código vamos a hacer uso de la etiqueta script nuevamente justo antes del cierre de nuestra etiqueta body.

<!-- ... -->
<body>
<!-- ... -->
<script>
// Aqui va nuestro codigo de JavaScript
</script>
</body>
<!-- ... -->

Definiendo nuestra fuente de datos

Vamos a empezar por declarar un arreglo de nombre tareas que servirá como nuestra fuente de datos y contendrá las tareas independientemente del estado en que se encuentren.

<!-- ... -->
<body>
<!-- ... -->
<script>
let tareas = [];
</script>
</body>
<!-- ... -->

La función renderizarTareas

Esta función nos ayudara a manipular el contenido de cada uno de los contenedores reservados para renderizar los elementos del arreglo tareas y recibirá como parámetro el estado de la columna que queramos actualizar: todo, doing, done.

Partiendo nuestro código

  1. Comenzamos por declarar una variable llamada tareasHTML (línea 8) que tendrá el código HTML en formato de texto que resulte de concatenar cada uno de los elementos según el estado enviado como argumento.
  2. Filtramos el arreglo tareas con el método filter (línea 10) para obtener solo las tareas dependiendo del estado enviado, recorremos cada uno de los elementos con un foreach (líneas 11–21), debemos recalcar aquí un detalle muy importante y tiene que ver con el boton que nos va a ayudar que cambiemos el estado de nuestras tareas (líneas 13–15) y es que debemos notar que adicional al argumento event se deberá enviar el id y el estado de la tarea. Por ultimo concatenamos el HTML con la información de la tarea dentro de nuestro loop (línea 17).
  3. Finalmente debemos renderizar todo el HTML que formamos dentro de nuestros contenedores, para eso obtenemos la referencia de nuestro contenedor a través de document.getElementById (línea 22) y luego simplemente configuramos como contenido el string resultante de la variable tareasHTML (línea 23).

Viendo nuestro HTML (todoContainer) siendo actualizado con la función renderizarTareas, luciría más o menos de la siguiente forma:

Ilustración de la manipulación del DOM requerida

La función agregarNuevaTarea

La función agregarNuevaTarea hará que vayamos agregando nuevas tareas a nuestro arreglo tareas, una vez actualizado el arreglo y haciendo uso de localStorage vamos a guardar esta información en la memoria de nuestro navegador y por último actualizaremos el div id="todoContainer" . La función será invocada desde el evento onsubmit de nuestro formulario de nueva tarea.

Partiendo nuestro código

  1. Comenzamos por obtener el valor de nuestra única caja de texto presente en nuestro formulario (línea 11) para luego adjuntarlo como información de nuestra nueva tarea (líneas 12–16) que será agregada a nuestro arreglo tareas (línea 17) y por último actualizamos el contenido de el item tareas en nuestro localStorage (línea 18).
  2. Invocamos a la función renderizarTareas (línea 19)enviando como argumento el estado todo ya que es la columna de este estado la que debe ser actualizada luego de agregar un nuevo elemento dentro del arreglo tareas.
  3. Por último, reseteamos el formulario para borrar todo su contenido y así quede listo para el ingreso de una nueva tarea (línea 20).

La función cambiarEstadoTarea

La función cambiarEstadoTarea va a cambiar el estado de un elemento en nuestro arreglo, actualizar nuestro localStorage y va a renderizar las columnas con la nueva información de tareas actualizada.

Partiendo nuestro código

  1. Comenzamos por buscar el índice de la tarea que debe ser actualizada basados en el id que recibimos como parámetro (línea 11), luego el parámetro estadoAnterior nos va a ayudar a determinar cuál será el estado al cual deberá ser actualizada nuestra tarea (líneas 13–19), una vez actualizada nuestra tarea dentro del arreglo, vamos a grabar esta información en nuestro navegador con localStorage.
  2. Por último, invocamos a la función rederizarTareas 2 veces, la primera vez para actualizar la columna con el estado anterior (línea 21) lo que hará que la tarea que estamos cambiando de estado desaparezca de esta columna y una segunda (línea 22) vez para que la tarea aparezca en la columna correspondiente al nuevo estado de la tarea.

Obteniendo las tareas desde localStorage

Si en este punto pruebas la aplicación notarás que funciona bien, excepto que si actualizas el navegador todas las tareas van a desaparecer, esto se debe a que aún no hemos inicializado nuestro arreglo tareas desde la información que previamente dejamos en localStorage , así que vamos por ello:

Partiendo nuestro código

  1. Comenzamos por invocar la función localStorage.getItem enviando como argumento la clave que contiene la información de nuestras tareas (línea 7), no olvidar que la información almacenada en localStorage esta dada en formato string por lo que debemos transformar la información a través de la función JSON.parse.
  2. Por último hacemos uso de nuestra función renderizarTareas 3 veces (líneas 8–10), una vez por cada estado.

Resultado final

El resultado final uniendo todas las partes de nuestro código debería lucir así:

En nuestro navegador, se debería ver la siguiente funcionalidad:

Kanban board UI — resultado final
Kanban board UI — resultado final

Conclusión

Uno de los aspectos mas notorios al usar Vanilla JavaScript es que no nos provee una forma de conectar nuestro HTML de forma automática (binding), como lo hace cualquier framework de JavaScript en la actualidad, por lo contrario debemos hacerlo de forma manual como se ve en las líneas 70, 71, 76 donde de manera imperativa especificamos que debe hacer cada parte de nuestro HTML (extraer datos desde la vista, renderizar de vuelta datos a la vista), lo que al momento de pretender desarrollar una aplicación a gran escala puede resultar un dolor de cabeza ya que seguramente vas a tener la necesidad de modificar el HTML desde diversas funciones lo que puede resultar en que tengas código espagueti , incomprensible y difícil de interpretar.

Siguiente paso

En el siguiente tutorial veremos cómo hacer lo que hemos hecho en este post, pero usando una forma declarativa con ReactJs, observaremos como desde la construcción de nuestra vista podemos interpretar lo que nuestra aplicación puede hacer, conectando un “modelo de datos” o estado, a diferencia de Vanilla JavaScript donde ciertas partes de nuestro HTML no tienen sentido a simple vista, hasta que revisamos el código.

Puedes clonar el resultado final de este post desde GitHub.

Video

--

--