Lista de tareas pendientes con Angular - Ejecutando proyecto con ng serve

Lista de tareas pendientes con Angular – ToDo list

En este post te mostraré un proyecto muy sencillo creado con Angular. Se trata de una lista de tareas pendientes, ToDo list, to-do list o como sea que le llames.

Vamos a usar el framework Angular y el lenguaje de programación TypeScript para crear una lista de tareas por hacer. Tendrá las opciones de agregar, eliminar, editar y marcar como terminada.

Por cierto, en este caso vamos a usar localStorage para almacenar la lista pero bien podrías usar una API con un lenguaje como PHP o cualquier otra cosa.

Para tener el proyecto simple me he enfocado a no usar frameworks CSS, así que solo será HTML plano. De todos modos lo que importa es cómo vamos a manejar la lista de tareas pendientes con Angular.

Estructura del proyecto

Lista de tareas pendientes con Angular - Ejecutando proyecto con ng serve
Lista de tareas pendientes con Angular – Ejecutando proyecto con ng serve

He creado el proyecto con la CLI de Angular, así que tiene la estructura que ya conoces. Basta con contar con la CLI, descargar el código, ejecutar ng serve y visitar localhost:4200.

Además, he creado un servicio para guardar y obtener las tareas pendientes. La gestión de la lista está en un solo componente, ya que por ahora no he creado más componentes.

Clase de Tarea Pendiente

Lo que vamos a gestionar es una tarea pendiente, así que le he creado una clase con TypeScript:

export class TareaPendiente {
    public nombre: string
    public terminada: boolean
    constructor(nombre: string, terminada?: boolean) {
        this.terminada = terminada ? terminada : false;
        this.nombre = nombre;
    }
}

Y esta clase será la que vamos a usar para toda la gestión de nuestra ToDo list con Angular.

Servicio para gestión de tareas pendientes en Angular

El servicio que mencioné anteriormente queda así, es muy simple. Lo que quiero que notes es que puedes modificar este servicio en caso de que quieras cambiar el almacenamiento a un lugar del servidor.

import { Injectable } from '@angular/core';
import { TareaPendiente } from './tarea-pendiente';

@Injectable({
  providedIn: 'root'
})
export class TareasService {
  CLAVE_LOCAL_STORAGE = "tareas_angular"

  constructor() { }

  obtenerTareas(): TareaPendiente[] {
    return JSON.parse(localStorage.getItem(this.CLAVE_LOCAL_STORAGE) || "[]")
  }
  guardarTareas(tareas: TareaPendiente[]) {
    localStorage.setItem(this.CLAVE_LOCAL_STORAGE, JSON.stringify(tareas))
  }
}

Fíjate en que estoy usando la clase que te mostré anteriormente. Y en este caso solo estoy implementando dos funciones: la de guardar y la de obtener.

Si te quedan dudas de cómo estoy guardando la lista en el almacenamiento local te invito a leer el post sobre localStorage. Lo único que hago es codificar y decodificar la lista como JSON al momento de guardarla y obtenerla.

Obtener tareas

En el componente de la interfaz de la lista estamos obteniendo las tareas. Primero en el ngOnInit:

  obtenerTareas() {
    this.tareas = this.tareasService.obtenerTareas();
  }
  ngOnInit() {
    this.obtenerTareas();
  }

Ahora tenemos todas las tareas pendientes como un arreglo. A ese arreglo le haremos las operaciones, y cada que una tarea pendiente se elimine o marque como terminada / no terminada vamos a guardar ese arreglo.

Por cierto, para dibujar la lista tenemos lo siguiente:

<ul>
    <li *ngFor="let tarea of tareas;let indice = index;" [class.tachado] ="tarea.terminada">
        <input [(ngModel)]="tarea.terminada" (change)="cambiarEstadoDeTarea()" type="checkbox">
        {{tarea.nombre}}
        <a  (click)="eliminarTarea(indice)" class="enlace-eliminar">&times;</a>
    </li>
</ul>

Como puedes ver estamos usando un ngFor. En este caso cada tarea tiene un input que indica su estado, así como un botón para eliminar la tarea.

Agregar tarea pendiente

Para agregar basta con tener un input y un botón:

<label for="tarea">Nombre de la tarea:</label>
<input placeholder="Ingresa la tarea" type="text" [(ngModel)]="nombreTarea" id="tarea">
<button [disabled]="!nombreTarea" (click)="guardarTarea()">Guardar</button>

Nuestro input está relacionado a una variable en TypeScript. La variable se llama nombreTarea, y esa nos servirá para recuperar el nombre de la tarea así como para deshabilitar el botón si es que la misma está en blanco.

Ya en el lado de TypeScript tenemos la función que simplemente agrega una nueva tarea al arreglo y guarda toda la lista:

  guardarTarea() {
    const nuevaTarea = new TareaPendiente(this.nombreTarea);
    this.tareas.push(nuevaTarea);
    this.tareasService.guardarTareas(this.tareas);
    this.obtenerTareas();
    // Y limpiamos el input
    this.nombreTarea = "";
  }

Usamos push para agregar el elemento al arreglo en la línea 3, luego guardamos la tarea invocando al servicio y finalmente refrescamos la lista.

Tarea terminada

Ya sea para marcar o desmarcar una tarea, necesitamos escuchar el evento change del input.

En ese evento simplemente guardamos la lista de tareas, ya que el estilo de la clase se aplicará con angular (Específicamente la clase tachado, que puedes ver en el HTML del renderizado de la lista).

  cambiarEstadoDeTarea() {
    // No debemos hacer nada con la tarea, ya que el input con el ngModel ha
    // cambiado la variable, así que solo guardamos las tareas tal y como están
    // Es decir, this.tareas ya está modificada hasta este punto
    this.tareasService.guardarTareas(this.tareas);
  }

Eliminar tarea

Finalmente veamos cómo eliminar una tarea. Recuerda que esto será invocado desde un elemento a de la lista que creamos anteriormente.

Lo que hacemos es eliminar el elemento del arreglo usando su índice, y después guardamos la lista usando el servicio.

  /*
  Nota: aquí utilizo el índice porque solo trabajo con un array. Si tú usas
  una base de datos probablemente quieras usar el ID del elemento en lugar del índice
   */
  eliminarTarea(indice: number) {
    // Primero le preguntamos al usuario
    const confirma = confirm("¿Realmente quiere eliminar la tarea?");
    if (!confirma) {
      return;
    }
    // Eliminamos del arreglo y guardamos
    this.tareas.splice(indice, 1);
    this.tareasService.guardarTareas(this.tareas);
  }

Por cierto, al eliminar una tarea pendiente de la ToDo list en Angular estamos solicitando confirmación del usuario con la función confirm.

Compilando para producción

Si quieres llevar esto a producción simplemente ejecuta ng build y copia los archivos de dist a un servidor.

Solo te aviso que en el caso de Apache y GitHub Pages debes abrir el index.html generado y cambiar el <base href="/"> de modo que quede así:

<base href="./">

Fíjate que solo he agregado un punto antes de la barra. Estoy seguro de que se puede cambiar en tiempo de compilación en algún archivo, pero no he investigado.

Vídeo de YouTube

Te dejo con ayuda adicional para que entiendas el código de mejor manera a través de un vídeo:

Poniendo todo junto

Te dejo una demostración de la lista de tareas por aquí, y el código completo en este otro enlace.

Por cierto, en el código vas a encontrar una carpeta llamada docs. No es importante, solo tiene la aplicación compilada para que GitHub me permita alojarla en GitHub pages, por ello es que debe tener ese nombre.

ToDo list con Angular y TypeScript - Ejemplo de proyecto con localStorage
ToDo list con Angular y TypeScript – Ejemplo de proyecto con localStorage

Anteriormente ya hice una lista de tareas con JavaScript puro, y por eso es que ahora quise hacerla usando Angular.

Si te gusta este framework te invito a ver otros proyectos creados con Angular.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *