taller1 - keblato/TutorialesTalleres-Angular GitHub Wiki

Taller 1

Objetivos

Al finalizar este taller el estudiante estará en capacidad de

  • Construir un sitio web responsive usando Html y CSS.
  • Utilizar el framework Bootstrap para la maquetación de sitios web.
  • Construir funciones en typescript.

Contexto

Construcción de la hoja de vida del estudiante. Debe contener la imagen del estudiante, sus datos personales y los cursos que está tomando actualmente. La siguiente figura muestra un mockup final de la hoja de vida del estudiante.

mockup
Figura 1: Mockup Hoja de vida del Estudiante

Paso 1 (Construcción inicial de la hoja de vida del estudiante.)

Para este paso vamos a utilizar sólo html. Por lo tanto, todos los elementos agregados estarán ubicados uno tras otro a modo de lista.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Taller 1</title>
</head>
<body>
    <h1>Ana María Suarez</h1>
    
    <img src="./avatar.png" height="300px" width="300px" alt="Avatar">
    <h2>Datos Personales</h2>
    <table>
        <thead>
            <tr>
                <th></th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Código</td>
                <td>10234320</td>
            </tr>
            <tr>
                <td>Cédula</td>
                <td>12221122</td>
            </tr>
            <tr>
                <td>Edad</td>
                <td>25 Años</td>
            </tr>
            <tr>
                <td>Dirección</td>
                <td>Calle falsa 123</td>
            </tr>
            <tr>
                <td>Teléfono</td>
                <td>018002500</td>
            </tr>
        </tbody>    
    </table>
    <h2>Cursos Actuales</h2>
    <table>
            <thead>
                <tr>
                    <th>Curso</th>
                    <th>Profesor</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Ingeniería de SW</td>
                    <td>Pablo Picasso</td>
                </tr>
                <tr>
                    <td>Futbol I</td>
                    <td>Juan Piña</td>
                </tr>
                <tr>
                    <td>Algoritmos Genéticos</td>
                    <td>María de la Rosa</td>
                </tr>
            </tbody>    
        </table>
</body>
</html>

Solución

paso1.PNG
Figura 2: Paso 1

Paso 2 (Implementación de Bootstrap 4 al sitio web creado en el paso 1. )

  • Importar Bootstrap al sitio web: Para importar los estilos de Bootstrap se debe agregar la siguiente etiqueta dentro del elemento .
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Taller 1</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
</head>
Nota: Algunos componentes de Bootstrap requieren importar los scripts JQuery y Popper.js. Para este taller no serán necesarios. Para más información Getting Started - Bootstrap
  • Una vez implementado Bootstrap en el sitio web vamos a establecer la estructura visual del sitio. Como vemos en el mockup existen dos columnas y cada una tiene un título y una tabla. Bootstrap permite la distribución de elementos mediante el uso de las class: row y col, las cuales definen la ubicación de los elementos en el DOM.

Definamos un contenedor y dentro de éste una fila que contiene dos columnas.

boxes.png
Figura 3: Contenedor para la Hoja de vida del Estudiante

Lo cual en bootstrap equivale a:

<body>
    <div class="container">
        <div class="row">
            <div class="col-md-6">
                <h1>Ana María Suarez</h1>
                <img src="./avatar.png" height="300px" width="300px" alt="Avatar">
                <h2>Datos Personales</h2>
                <table>
                    <thead>
                        <tr>
                            <th></th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>Código</td>
                            <td>10234320</td>
                        </tr>
                        <tr>
                            <td>Cédula</td>
                            <td>12221122</td>
                        </tr>
                        <tr>
                            <td>Edad</td>
                            <td>25 Años</td>
                        </tr>
                        <tr>
                            <td>Dirección</td>
                            <td>Calle falsa 123</td>
                        </tr>
                        <tr>
                            <td>Teléfono</td>
                            <td>018002500</td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <div class="col-md-6">
                <h2>Cursos Actuales</h2>
                <table>
                    <thead>
                        <tr>
                            <th>Curso</th>
                            <th>Profesor</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>Ingeniería de SW</td>
                            <td>Pablo Picasso</td>
                        </tr>
                        <tr>
                            <td>Futbol I</td>
                            <td>Juan Piña</td>
                        </tr>
                        <tr>
                            <td>Algoritmos Genéticos</td>
                            <td>María de la Rosa</td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</body>

Desafíos

  • Agregar clases de bootstrap a las Tablas y agregar el header de la tabla Cursos Actuales en Negro.
  • Agregar la clase Card a las tablas de tal forma que se vea la separación de las secciones.
  • En ocasiones bootstrap no es suficiente para satisfacer la maquetación deseada. Para ello es posible que usted deba agregar un archivo de estilos css que le permita definir margenes, fuentes personalizadas, colores, etc. Ver taller-básico de html.

Solución simple

paso2.PNG
Figura 4: Paso 2

Paso 3 (Manejo de datos con TypeScript)

Typescript

TypeScript es un superset de Javascript, esto significa que cuenta con todas las carácterísticas de Javascript más otras funcionalidades y herramientas de programación orientada a objetos. Como sabemos Javascript es dinámicamente tipado. Por lo tanto, los programas escritos en Javascript no conocen el tipo de datos de una variable hasta que la variable es asignada en ejecución o runtime. La variable puede ser reasignada con un tipo diferente sin problemas o warnings. Lo anterior, es el dolor de cabeza para muchos desarrolladores de aplicaciones grandes, ya que puden aparecen bugs que fueron pasados por alto y que solo son visibles en ejecución.

Typescript, por otro lado, usa tipado estático. Las variables pueden tener declarado un tipo específico de dato y typescript se encargará de verificar que los datos asignados a las variables sean coherentes con la declaración inicial.

Recomendamos visitar el siguiente link donde podrá encontrar un tutorial básico de Typescript.

Definiendo clases

Javascript a partir de ECMAScript2015 introdujo clases al lenguaje. Sin embargo, es importante tener en cuenta que estas clases no cambian la herencia basada en prototipos del lenguaje. Typescript permite definir clases antes de que sean transpiladas a javascript ES6. Por lo tanto, los desarrolladores pueden extender clases para construir nuevas clases usando herencia.

Retomando el enunciado del taller, vamos a crear dos clases: Student and Course

export class Course {

  name: string;
  credits: number;
  professor: string;

  constructor(name: string,credits:number, professor: string ) {
        this.name = name;
        this.credits = credits;
        this.professor = professor;
    }
}
import { Course} from './course';

export class Student{

  completeName: string;
  avatar:string;
  code: number;
  cardId: number;
  age: number;
  address: string;
  phone:string;
  currentCourses:Course[];
  
  constructor(completeName: string,code: number, cardId: number  ) {
        this.completeName = completeName;
        this.code = code;
        this.cardId = cardId;
    }

}

Como se puede observar la sintaxis es similar a Java o C#. Observe cómo la clase Student declara el atributo currentCourses de tipo array de Course.

Primera función en Typescript

Vamos a construir una función que sea capaz de leer los datos de un arreglo de objetos curso y finalmente los despliegue en la tabla de curso actuales (DOM).

Para completar este paso puede abrir el siguiente proyecto en stackBlitz o realizar la instalación manual de typescript según el tutorial básico de Typescript.

En el proyecto aparecen dos archivos (dataCourses y dataStudent) los cuales tienen información dummy para un estudiante y sus cursos. La función que llamaremos renderCoursesInTable recibirá como parámetro los cursos y luego los pintará en la tabla de cursos actuales.

const coursesTbody: HTMLElement = document.getElementById('courses');

function renderCoursesInTable(courses: Course[]): void {
  courses.forEach((course) => {
    let trElement = document.createElement("tr");
    trElement.innerHTML = `<td>${course.name}</td>
                           <td>${course.professor}</td>
                           <td>${course.credits}</td>`;
    coursesTbody.appendChild(trElement);
  });
}

Tres cosas para resaltar en la función anterior:

  • La primera línea define una constante de tipo HTMLElement. Si asignamos un número a esta constante tendremos un error de asignación, debe ser HTMLElement.
  • El argumento de la función define que sólo puede recibir un array de objetos Course y la función no devolverá ningún valor (void).
  • La función como primer paso recorre uno a uno los cursos (forEach) y por cada curso crea una etiqueta tr y dos etiquetas hijas td con la información del nombre del curso, de los créditos y del profesor. Reconoces la expersión (course) => {} ?. Está es una función de flecha o arrow function que simplifica la declaración de una función y a su vez realiza un bind del objeto this. Ver Arrow function

Calcular número de créditos actuales

Vamos a crear una función que recorra todos los cursos actuales para obtener el total de créditos del estudiante.

function getTotalCredits(courses: Course[]): number {
  let totalCredits: number = 0;
  courses.forEach((course) => totalCredits = totalCredits + course.credits);
  return totalCredits;
}

Filtrar por nombre del curso

Es este apartado vamos a crear un filtro sobre el nombre del curso. El usuario debe agregar el nombre o iniciales del curso y deben aparecer las coincidencias respectivas.

En el html agregamos un form con un input y un botón, justo encima de la tabla, así:

<form style="margin:10px;">
    <div class="form-row">
      <div class="col">
      	<input type="text" class="form-control" id="search-box" placeholder="Filtrar por nombre">
      </div>
      <div class="col">
      	<button type="button" id="button-filterByName" class="btn btn-success">Aplicar</button>
      </div>
    </div>
</form>

En el archivo typescript creamos dos funciones: applyFilterByName para obtener el texto de búsqueda, limpiar la tabla y llamar a la búsqueda y finalmente searchCourseByName que se encarga de ejecutar la búsqueda mediante el uso de filter.

function applyFilterByName() {
  let text = inputSearchBox["value"];
  clearCoursesInTable();
  let coursesFiltered: Course[] = searchCourseByName(text, dataCourses);
  renderCoursesInTable(coursesFiltered);
}

function searchCourseByName(nameKey: string, courses: Course[]) {
  return nameKey === '' ? dataCourses : courses.filter((course) => course.name.includes(nameKey));
}

Finalmente, debemos relacionar el evento onClick con la función applyFilterByName de la siguiente forma:

btnfilterByName.onclick = () => applyFilterByName();

Solución Simple:

paso3.PNG
Figura 5: Paso 3

Ver en StackBlitz

Desafíos

  • Completar la información personal de la estudiante a partir de un objeto de typescript (archivo dataStudent).
  • Realizar un filtro por rangos de créditos de los cursos. Por ejemplo, fijar un valor mínimo de créditos y un valor máximo y al aplicar este filtro deben aparecer los cursos que pertenezcan a este intervalo.
⚠️ **GitHub.com Fallback** ⚠️