shoppingcart - keblato/TutorialesTalleres-Angular GitHub Wiki

Ejemplo ShoppingCart

Este ejemplo es una adaptación del que se encuentra aquí.

Vamos a desarrollar el ejemplo del Shopping Cart en Angular. Los requerimientos:

  • Se debe poder crear ítems de compra con descripción, cantidad y costo
  • Se debe incluir el subtotal de cada ítem.
  • Se debe totalizar toda la lista del Shopping Cart
  • Se debe poder borrar un ítem de compra.

Stackblitz

El código de este ejemplo está en: https://stackblitz.com/edit/shoppingcart-isis

Para poder modificar el ejercicio, cree una cuenta en Stackblitz, y haga click en "Fork". De esta forma, podrá guardar los cambios que realice al resolver los desafíos.

Diseño de la Interfaz

Primero definimos un prototipo de cómo debería verse la aplicación:

ui-shoppincart.PNG
Figura 1: Interfaz usuario applicación shopping cart

Diseño de la aplicación

Por ser esta una aplicación simple, vamos a definir un módulo principal y el componente de ShoppingCart. El siguiente diagrama muestra la decisión de diseño.

shoppingcart.jpeg
Figura 2: Diagrama de clases de la applicación shopping cart

Como se puede ver, tenemos el módulo principal AppModule con su componente por defecto AppComponent. Tenemos un componente adicional ShoppingCartComponent que tiene el modelo del shopping cart, llamado invoice, y, dado lo simple de la lógica, la hemos definido directamente como métodos del componente.

Vale la pena mencionar que siempre que hablamos de un componente, estamos incluyendo al menos 4 elementos:

  1. La clase componente que es la que se muestra en el diagrama,
  2. La vista del componente (el Html),
  3. Los estilos que se le aplicarán a la vista y
  4. La especificación de las pruebas.

También, en el diagrama estamos mostrando un comentario asociado con cada componente que incluye "decoraciones" o metadatos que serán utilizados por Angular cuando despliegue la aplicación. En el caso del componente estos son: el selector que se refiere al tag de html que se crea para que cuando se utilice dentro de un html allí se despliegue el componente y el nombre del archivo que contiene la definición de la vista del componente.

Estructura del proyecto

Este proyecto sigue una estructura estándar de proyectos Angular. Dentro de la carpeta appestán los módulos (en este caso sólo uno) y los componentes. El componente shopping-cart está dentro de su propia carpeta. En la siguiente figura, los archivos que están encerrados en el cuadro verde corresponden al componente ShoppingCartComponent.

files-shoppincart.PNG
Figura 3: Estructura de archivos de la applicación shopping cart
Note que hay un archivo llamado item.model.ts, contiene la definición de la clase item.

El archivo que está abierto index.html utiliza el selector o tag html que fue definido en el AppComponent, ver Figura 2, es decir my-app. Allí tambien hay otro meta-dato llamado templateUrlcuyo valor es el nombre del archivo html de la vista del componente ShoppingCartComponent. Esto significa que cuando se encuentre el tag my-app este se remplazará por la vista del componente.

Este template se muestra en la siguiente figura:

shoppingcart_html.PNG
Figura 4: Template o vista del componente ShoppingCartComponent

El html anterior utiliza:

  • Estilos de bootstrap +4.1 que fueron importados en el archivo stype.css que se encuentra en la raíz del proyecto.
  • Evaluación de expresiones {{ ..| ..}}. Tiene dos partes, la expresión que se evaluará y el formato en el que se desplegará la respuesta. Por ejemplo, en la línea 27 se invoca la funcion subtotal y la respuesta se formatea como una moneda.
  • Marcado de Angular como por ejemplo [(ngModel)] esta directiva significa un "two-way binding"; cuando el campo es actualizado desde la vista, por ejemplo por el usuario, la variable también toma ese valor. Si la variable es actualizada desde el código, el campo en la vista también es actualizado.

Este comportamiento se puede apreciar si ud. cambia los valore sobre la forma de la cuenta del carritos. Este cambio queda reflejado en la variable invoice.

ui-shoppincart-2.PNG
Figura 5: "two-way binding"

Descripción del componente ShoppingCartComponent

El componente inicia importando el modelo de un item.

La razón por la que se utilizan los modelos es para lograr que su definición y tratamiento (En este caso del item) sean los mismos en toda la aplicación. Las ventajas de esto son más claras en una aplicación más grande, pero imagine que va a agregar un nuevo componente para manejar las facturas.

Si no existiera el modelo, el código perdería claridad con respecto a qué es un item en cada uno de los componentes. Esto se tendría que definir en cada uno de ellos, o en el peor de los casos en ninguno, y las modificaciones podrían por ejemplo no replicarse.

El constructor del componente inicializa la factura como una lista vacía, y le agrega un nuevo item utilizando el modelo.

ShoppingCartComponent-1.png
Figura 6: "Estructura básica del componente"

Con respecto a las operaciones del ShoppingCart, para este ejemplo de introducción, se ha decidido implementarlas dentro del componente.

El componente cuenta con 4 métodos:

  • addItem que agrega un nuevo item a la factura
  • deleteItem que elimina el item que recibe por parámetro de la factura
  • subTotal que calcula y mantiene actualizada la variable del subtotal de cada item (su precio * su cantidad)
  • total que calcula y mantiene actualizado el valor de la factura
ShoppingCartComponent-2.png
Figura 7: "Métodos del componente"

Desafíos

  1. Modifique el componente ShoppingCartComponent para que al inicializar, el producto que agregue tenga un valor de 99,95.
  2. Agregue al modelo item el atributo type que puede ser de 3 tipos: meat, beverage o fruit. Haga las modificaciones necesarias para agregar esta columna a la tabla del shopping cart. El campo debe ser de tipo select.
  3. Utilizando los estilos de Bootstrap 4.1, cambie los botones para que sean de tipo "Outline button" y haga una modificación adicional de su preferencia para personalizarlos (ej. tamaño, fuente, etc.)
  4. Es usual en la estructura de los proyectos Angular que la lógica de los componentes se defina en un servicio. Cambie a un servicio(@Injectable) la lógica del componente ShopingCartComponent. Es decir, todas aquellas operaciones cuya responsabilidad difiera de interactuar con la vista. El componente debe inyectar un servicio y hacer llamados a este para recibir el resultado de las operaciones.