Herramientas de usuario

Herramientas del sitio


clase:daw:diw:1eval:tema03

¡Esta es una revisión vieja del documento!


Filtros

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. <boton></boton>
  • 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

<button class="boton">Aceptar</button>

.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 <boton></boton> en el app.html

<style>
</style>
  
<h1 >Hola mundo</h1>
  
<button matButton="filled">
  Aceptar
</button>

<br>
<br>

<boton></boton>
  
<router-outlet />

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 <ng-content></ng-content> en el boton.html

<button class="boton">
  <ng-content></ng-content>
</button>

Y ahora ya podremos cambiar el texto:

<style>
</style>
  
<h1 >Hola mundo</h1>
  
<button matButton="filled">
  Aceptar
</button>

<br>
<br>

<boton>Hola mundo</boton>
  
<router-outlet />

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:

<boton [backgroundColor]="'#FF0000'" [color]="'#00FF00'">Hola mundo</boton>

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:

<button class="boton" style="color:{{color}};background-color:{{backgroundColor}}">
  <ng-content></ng-content>
</button>

  • Usando [style] de Angular:

<button class="boton" [style.color]="color" [style.backgroundColor]="backgroundColor">
  <ng-content></ng-content>
</button>

  • Usando [ngStyle] de Angular:

<button class="boton" [ngStyle]="{'color': color, 'background-color': backgroundColor}">
  <ng-content></ng-content>
</button>

  • Por último lo ideal siempre es usar clases CSS y evitar usar style:

<button class="boton" [ngClass]="[colorClass, backgroundClass]">
  <ng-content></ng-content>
</button>

<button class="boton color--{{color}} background--{{backgroundColor}}">
  <ng-content></ng-content>
</button>

<button class="boton" [ngClass]="['color--'+color, 'background--'+backgroundColor]">
  <ng-content></ng-content>
</button>

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

Así que realmente lo que queremos es solo definir la función del botón.De forma que se use de la siguiente manera:

<boton [funcion]="'peligrosa'">Hola mundo</boton>

  • 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:

<button class="boton funcion--{{funcion}}">
  <ng-content></ng-content>
</button>

Notar el truco de class="funcion–{{funcion}}"
  • Otra forma alternativa sería:

<button class="boton" [ngClass]="['funcion--'+funcion]">
  <ng-content></ng-content>
</button>

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 <button> a <a>

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';
  @Input() href:string="";

}

  <a class="boton funcion--{{funcion}}" [attr.href]="href || null">
    <ng-content></ng-content>
  </a>

Hay que destacar que además de usar ahora href también hemos cambiado la etiqueta a <a>.

Hemos puesto

[attr.href]="href || null"

en vez de simplemente

href={{ href }}

porque si no hay nada en href, no se añadirá el atributo

Acción onClick

Queremos que se ejecute la función alerta() de nuestra aplicación al pulsar en el botón.

import { Component, signal } from '@angular/core';
import { RouterOutlet } from '@angular/router';
 
 
@Component({
  selector: 'app-root',
  imports: [RouterOutlet],
  templateUrl: './app.html',
  styleUrl: './app.scss'
})
export class App {
  protected readonly title = signal('prueba');
 
  alerta() : void {
    alert('Hola mundo');
  }

}

En el HTML lo indicaremos así

<style>
</style>
   
<h1 >Hola mundo</h1>
   
<button matButton="filled">
  Aceptar
</button>
 
<br>
<br>
 
<boton [funcion]="'peligrosa'" (onClick)="alerta()"  >Hola mundo</boton>
   
<router-outlet />

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 <a> 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<void>();

  handleOnClick(): void {
    this.onClick.emit();
  }

}


  <a class="boton funcion--{{funcion}}" [attr.href]="href || null" (click)="handleOnClick()">
    <ng-content></ng-content>
  </a>

Ejercicios

Ejercicio 1

Usando el elemento HTML de <progress>.

<label for="file">File progress:</label>

<progress id="file" max="100" value="70">70%</progress>

Crea el componente <progreso>

<progreso  [title]="'File progress:'" [porcentajeRealizado]="70" />

<boton (onClick)="incrementar()">Incrementar 10</boton>

y que muestre:

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

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
Alternativa
Peligrosa
clase/daw/diw/1eval/tema03.1762357307.txt.gz · Última modificación: por Lorenzo