====== 3. Creación de componentes ====== En este tema vamos a crear nuevo componentes de Angular ===== Crear tu nuevo componente botón ===== Vamos a crear nosotros un nuevo componente ''boton''. Para ello vamos a crear los 3 ficheros que necesitas todo componente: * ''boton/boton.ts'': El código TypeScript que tiene la lógica del botón * ''boton/boton.html'': El HTML correspondiente al botón * ''boton/boton.scss'': Los estilos en SASS del botón. Por ahora es simplemente estilos CSS. Los 3 ficheros los crearás dentro de la carpeta ''src/app/components/ui'' src/ └─ minecraft/ └─ components/ ├─ ui/ │ ├─ boton/ │ │ ├─ boton.ts │ │ ├─ boton.html │ │ └─ boton.scss │ └─ panel/ └─ paginas/ ├─ minecraft-main/ │ ├─ minecraft-main.ts │ ├─ minecraft-main.html │ └─ minecraft-main.scss └─ productos/ ├─ productos.ts ├─ productos.html └─ productos.scss El contenido de cada uno de ellos será: import { Component } from '@angular/core'; import {CommonModule} from '@angular/common'; @Component({ selector: 'boton', imports: [CommonModule], templateUrl: './boton.html', styleUrl: './boton.scss' }) export class Boton { } La parte más importante es el objeto que se le pasa al decocador ''@Componente''. Veamos sus propiedades: * ''selector'': Es la etiqueta que usaremos cuando queramos usar el componente. '''' * ''imports'': Importamos otros componentes para poder usarlos dentro del HTML del componente. * ''templateUrl'': El nombre del fichero HTML * ''styleUrl'': El nombre del fichero SCSS de estilos .boton { font-family: sans-serif; font-size: 16px; padding: 6px; border-radius: 6px; border-width: 1px; border-style: solid; display: inline-block; cursor: pointer; text-decoration: none; border-color: #0056b8; background-color: #0056b8; color: #ffffff; } ===== Usando un componente ===== Como ya hicimos en el tema anterior, hay que importarlo en el ''.ts'' donde quedamos usarlo y añadirlo al array de ''imports''. Primero lo importamos en el ''app.ts''. Primero lo importamos en el ''app.ts''. import { Component, signal } from '@angular/core'; import { RouterOutlet } from '@angular/router'; import {MatButtonModule} from '@angular/material/button'; import { Boton } from './shared/ui/boton/boton'; @Component({ selector: 'app-root', imports: [RouterOutlet, MatButtonModule,Boton], templateUrl: './app.html', styleUrl: './app.scss' }) export class App { protected readonly title = signal('EjemploComponentesAngular'); } Y ahora ya podemos usar la etiquetya '''' en el ''app.html''

Hola mundo



===== Contenido de la etiqueta ===== Nuestros botones es muy pobre porque no permite indicar el texto del botón. Para poder hacerlo simplemente hay que usar la etiqueta '''' en el ''boton.html'' Y ahora ya podremos cambiar el texto:

Hola mundo



Hola mundo
===== Personalizar del componente ===== Vamos ahora añadir atributos a nuestro componente para poder personalizarlo. Para ello vamos a añadir propiedades a la clase TypeScript del componente con el decorador ''Input()'' Nuestro objetivo es poder hacer lo siguiente: Hola mundo Lo primero es añadir las propiedades ''backgroundColor'' y ''color'' a la clase ''Boton''. import { Component, Input } from '@angular/core'; import {CommonModule} from '@angular/common'; @Component({ selector: 'boton', imports: [CommonModule], templateUrl: './boton.html', styleUrl: './boton.scss' }) export class Boton { @Input() backgroundColor: string = '#0B5CD5'; @Input() color: string = '#F5F7FF'; } Para usarlas en el ''boton.html'' hay 3 formas distintas: * Directamente interpolando los valores: * Usando ''[style]'' de Angular: * Usando ''[ngStyle]'' de Angular: * Por último lo ideal siempre es usar clases CSS y evitar usar ''style'': Pero en ese caso hay que limitar los posibles valores, definir las clases, relacionarlas con las propiedades TypeScript. Esto lo veremos en el siguiente apartado. ===== Limitando los valores ===== En el apartado anterior hemos visto como definir los colores de los botones pero como vimos en el primer tema, realmente hay únicamente unos valores de colores que puede haber {{:clase:daw:diw:1eval:primary.png|}} {{:clase:daw:diw:1eval:alt-primary.png|}} {{:clase:daw:diw:1eval:rojo-primary.png|}} Así que realmente lo que queremos es solo definir la función del botón.De forma que se use de la siguiente manera: Hola mundo * Por lo tanto el atributo del botón va a ser ''funcion'' con los posibles valores de '''normal' | 'alternativa' | 'peligrosa''' . import {Component, Input} from '@angular/core'; import {CommonModule} from '@angular/common'; @Component({ selector: 'boton', imports: [CommonModule], templateUrl: './boton.html', styleUrl: './boton.scss' }) export class Boton { @Input() funcion:'normal' | 'alternativa' | 'peligrosa'='normal'; } * Ahora hay que definir las clases CSS en el archivo ''boton.scss'' .boton { font-family: sans-serif; font-size: 16px; padding: 6px; border-radius: 6px; border-width: 1px; border-style: solid; display: inline-block; cursor: pointer; text-decoration: none; border-color: #0056b8; background-color: #0056b8; color: #ffffff; } .funcion--normal { border-color: #0056b8; background-color: #0056b8; color: #ffffff; } .funcion--alternativa { border-color: #ed8936; background-color: #ed8936; color: #ffffff; } .funcion--peligrosa { border-color: #c53030; background-color: #c53030; color: #ffffff; } * Y por último relacionamos la propiedad TypScript ''funcion'' con las clases CSS en el HTML de la siguiente forma: Notar el truco de ''class="funcion--{{funcion}}"'' * Otra forma alternativa sería: ===== Acción de href ===== Por último vamos a añadir acciones al botón, como el ''onClick'' y el ''href'' Para crear el atributo ''href'' hay que hacer 3 cambios: * Añadir la propiedad ''href'' a la clase ''Boton'' * Usar la propiedad en el HTML * Cambiar de tipo ''

Hola mundo Para ello tenemos que hacer 3 cosas en el botón: * Decir que vamos a emitir un evento * Emitir el evento desde TypeScript * Enlazar el click de ''
'' con el TS import {Component, EventEmitter, Input, Output} from '@angular/core'; import {CommonModule} from '@angular/common'; @Component({ selector: 'boton', imports: [CommonModule], templateUrl: './boton.html', styleUrl: './boton.scss' }) export class Boton { @Input() funcion:'normal' | 'alternativa' | 'peligrosa'='normal'; @Input() href:string=""; @Output() onClick = new EventEmitter(); handleOnClick(): void { this.onClick.emit(); } } ===== Filtros ===== Angular permite modificar los datos cuando se interpolan en el html. * [[https://angular.dev/api/common/CurrencyPipe|currency]] : Permite mostrar un número como una moneda. En nuestro caso mostrará el símbolo del "€"

{{precio | currency}}

* [[https://angular.dev/api/common/DatePipe|date]] : Permite formatear una fecha

{{fechaCompra | date:'shortDate'}}

Los formatos predefinidos de fecha se pueden ver en [[https://angular.dev/api/common/DatePipe#pre-defined-format-options|Pre-defined format options]] ===== Ejercicios ===== ==== Ejercicio 1 ==== Usando el elemento HTML de [[https://developer.mozilla.org/es/docs/Web/HTML/Reference/Elements/progress|]]. 70% Crea el componente '''' Incrementar 10 y que muestre: {{:clase:daw:diw:1eval:file_progress.png?400|}} Añade en la página un botón de forma que al pulsarlo se incremente en 10 el valor. Para generar los ''id'' se usa la librería uuid npm install uuid npm install --save-dev @types/uuid import { v4 as uuidv4 } from 'uuid'; class MiClase{ uniqueId: string; constructor() { this.uniqueId =uuidv4(); } } ==== Ejercicio 2 ==== Crea un componente llamado panel que permita hacer los siguientes paneles {{:clase:daw:diw:1eval:ejercicio_paneles.png?400|}} Y crea una página HTML donde se vean los paneles. ==== Ejercicio 3 ==== Crea ahora un componente para crear los siguientes botones: ^ ^ Importancia ^^^ ^ Función | Primaria | Secundaria | Terciaria | | Normal | {{:clase:daw:diw:1eval:primary.png|}} | {{:clase:daw:diw:1eval:secondary.png|}} | {{:clase:daw:diw:1eval:tertiary.png|}} | | Alternativa | {{:clase:daw:diw:1eval:alt-primary.png|}} | {{:clase:daw:diw:1eval:alt-secondary.png|}} | {{:clase:daw:diw:1eval:alt-tertiary.png|}} | | Peligrosa | {{:clase:daw:diw:1eval:rojo-primary.png|}} | {{:clase:daw:diw:1eval:rojo-secondary.png|}} | {{:clase:daw:diw:1eval:rojo-tertiary.png|}} |