Herramientas de usuario

Herramientas del sitio


clase:daw:diw:angular-material

¡Esta es una revisión vieja del documento!


9. Angular: Material

En este tema vamos a crear un proyecto de Angular y usar en sus páginas los componentes de Angular Material: botones, cards, tabs y tablas.

Crear una aplicación de Angular

  • Instala Angular CLI v22

npm install @angular/cli@22 -g

Angular 22 necesita Node.js 22.22.3 o superior, 24.15 o superior o Node 26. Con un Node más antiguo ng no arranca y solo dice The Angular CLI requires a minimum Node.js version. Comprueba la versión con node -v.
  • Crea una aplicación de Angular

ng new prueba

Las preguntas que hacen se responden de la siguiente forma:

  • Which stylesheet system would you like to use? : Sass (SCSS)
  • Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)? : N
  • Which AI tools should Angular integrate with? : None

Establecer el idioma y moneda

Una cosa importante que siempre hay que hacer en un proyecto de Angular es definir que el idioma y la moneda es 'es-ES' y 'EUR' para ello modificaremos el fichero app.config.ts

import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';

import localeEs from '@angular/common/locales/es';
import { registerLocaleData } from '@angular/common';
import { LOCALE_ID,DEFAULT_CURRENCY_CODE } from '@angular/core';

registerLocaleData(localeEs);

export const appConfig: ApplicationConfig = {
  providers: [
    provideBrowserGlobalErrorListeners(),
    provideRouter(routes),
    {provide: LOCALE_ID, useValue: 'es-ES' },
    {provide: DEFAULT_CURRENCY_CODE, useValue: 'EUR' }
  ]
};

Ejecutar la App

  • Dentro de la carpeta del proyecto, ejecutar

ng serve

Modificar la página de inicio

  • Modifica el fichero app.html de forma que quede así:

<style>
</style>
 
<h1 >Hola mundo</h1>
 
<button >
  Aceptar
</button>
 
<router-outlet />

Los dos ficheros importantes son:

  • app.ts: Es el fichero TypeScript que contiene la lógica del componente. Es la parte que hay que programar.
  • app.html: Es el fichero HTML que contiene como se muestra ese componente.
  • Vamos a dejar el componente de app de la siguiente forma

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');


}

<style>
</style>
 
<h1 >Hola mundo</h1>
 
<button >
  Aceptar
</button>
 
<router-outlet />

Añadir CSS en Angular

Para añadir estilos CSS en Angular se usa el fichero de SASS que está en src/styles.scss donde se indican los estilos globales de la App. Aunque también cada componente tiene sus propios estilos.

Por otro lado si queremos añadir otros ficheros CSS o SASS deberemos añadirlos en el JSON de angular.json del raíz. En el nodo /projects/EjemploComponentesAngular/architect/build/options/styles Siendo EjemploComponentesAngular el nombre del proyecto.

Lo mismo se aplica a JavaScript que se añade en /projects/EjemploComponentesAngular/architect/build/options/scripts

Usar Bootstrap en Angular

Por ejemplo para usar Bootstrap junto a su JavaScript se haría de la siguiente forma:

npm install bootstrap@v5.3.8

Eso descargará bootstrap en node_modules/bootstrap/

Y ahora añadir el CSS y JavaScript en angular.json:

"build": {
    "styles": [
        "node_modules/bootstrap/dist/css/bootstrap.min.css",
        "src/styles.scss"
     ],
     "scripts": [
         "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
     ]
}

Usar Tailwind CSS en Angular

Para usar Tailwind CSS en Angular se añade con:

ng add tailwindcss

Eso hace todo lo necesario:

  • Instala tailwindcss, @tailwindcss/postcss y postcss.
  • Crea .postcssrc.json con el plugin de Tailwind para PostCSS.
  • Crea src/tailwind.css con @import 'tailwindcss'; y lo añade a styles de angular.json, delante de src/styles.scss.
Tailwind no se importa desde styles.scss: Tailwind 4 no está pensado para usarse con Sass, por eso va en su propio fichero .css.

Añadir Angular Material

La librería que vamos a usar en este módulo es Angular Material

  • Para añadirla al proyecto se usa:

ng add @angular/material

Las preguntas que hacen se responden de la siguiente forma:

  • Select a pair of starter prebuilt color palettes for your Angular Material theme : Azure/Blue

Usar Angular Material

Para usar un componente,primero debes importarlo en TypeScript.

Lo primero es buscar el componente en https://material.angular.dev/components/categories y una vez en el componente copiar el import que hay en la pestaña API.

Veamos el ejemplo con el componente Button.

  • Navega a Button y pincha en la pestaña de API, copia lo siguiente:

import {MatButtonModule} from '@angular/material/button';

  • Ve al fichero app.ts y pega lo que acabas de copiar.
  • En el array de imports añade lo que has importado; que es MatButtonModule:

  imports: [RouterOutlet,MatButtonModule],

El fichero app.ts debe quedar así:

import { Component, signal } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import {MatButtonModule} from '@angular/material/button';

@Component({
  selector: 'app-root',
  imports: [RouterOutlet, MatButtonModule],
  templateUrl: './app.html',
  styleUrl: './app.scss'
})
export class App {
  protected readonly title = signal('EjemploComponentesAngular');



}

  • Ahora ya puedes transformar un botón "normal" en un botón de Angular Material añadiendo el atributo matButton

<style>
</style>
 
<h1 >Hola mundo</h1>
 
<button matButton>
  Aceptar
</button>
 
<router-outlet />

Botones

El atributo matButton admite un valor para elegir el estilo del botón.

  • Cambia para que sea matButton="filled" y verás como cambia el estilo del botón.

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

Los estilos que hay son:

  • matButton: Botón de solo texto.
  • matButton="filled": Botón relleno con el color principal.
  • matButton="tonal": Botón relleno con un color más suave.
  • matButton="outlined": Botón con borde y sin relleno.
  • matButton="elevated": Botón con sombra.

<button matButton="filled">Pagar carrito</button>
<button matButton="outlined">Seguir comprando</button>
<button matButton>Cancelar</button>

Vuelve a los ejemplos que hay en Button y prueba otros estilos de botones

Iconos

Prueba ahora a añadir un icono de Angular Material; para ello ve a https://material.angular.dev/components/icon/overview

Y fíjate que ahora ya no se añade un atributo a una etiqueta HTML sino que directamente es la etiqueta mat-icon.

  • Importa el módulo y añádelo al array de imports de app.ts, igual que MatButtonModule:

import {MatIconModule} from '@angular/material/icon';

  • Y úsalo en el HTML:

<mat-icon>shopping_cart</mat-icon>

<button matIconButton>
  <mat-icon>delete</mat-icon>
</button>

  • matIconButton: Botón que solo tiene un icono.

El nombre del icono es el que aparece en Material Symbols.

Cards

Una card agrupa la información de una cosa: un producto, una noticia, un usuario…

  • Importa el módulo y añádelo al array de imports de app.ts, igual que MatButtonModule:

import {MatCardModule} from '@angular/material/card';

  • Y úsalo en el HTML:

<mat-card appearance="outlined" style="max-width: 300px">
  <mat-card-header>
    <mat-card-title>Monitor Acer Nitro 23.8"</mat-card-title>
    <mat-card-subtitle>89,99 €</mat-card-subtitle>
  </mat-card-header>
  <img mat-card-image src="https://logongas.es/lib/exe/fetch.php?cache=&media=clase:daw:diw:monitor.webp">
  <mat-card-content>
    <p>Monitor FHD de 200Hz con FreeSync Premium y HDR10.</p>
  </mat-card-content>
  <mat-card-actions>
    <button matButton="filled">Comprar</button>
    <button matButton>Ver detalles</button>
  </mat-card-actions>
</mat-card>

Las partes de la card son:

  • mat-card-header: La cabecera con mat-card-title y mat-card-subtitle.
  • mat-card-image: Atributo para una imagen que ocupa todo el ancho de la card.
  • mat-card-content: El contenido.
  • mat-card-actions: Los botones de la card.

Más información: Card

Tabs

Las pestañas (tabs) muestran distinto contenido en el mismo sitio, una pestaña cada vez.

  • Importa el módulo y añádelo al array de imports de app.ts, igual que MatButtonModule:

import {MatTabsModule} from '@angular/material/tabs';

  • Y úsalo en el HTML:

<mat-tab-group>
  <mat-tab label="Descripción">
    <p>Monitor FHD de 200Hz con FreeSync Premium y HDR10.</p>
  </mat-tab>
  <mat-tab label="Especificaciones">
    <p>23.8 pulgadas, panel VA, 1920x1080.</p>
  </mat-tab>
  <mat-tab label="Opiniones">
    <p>4,6 de 5 en 1472 opiniones.</p>
  </mat-tab>
</mat-tab-group>

  • mat-tab-group: El conjunto de pestañas.
  • mat-tab: Cada pestaña. El texto de la pestaña va en label y su contenido dentro de la etiqueta.

Más información: Tabs

Tablas

La tabla de Material no se escribe fila a fila: se le pasa un array con los datos y se define cómo se muestra cada columna.

  • Importa el módulo y define los datos y las columnas en el .ts:

import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import {MatTableModule} from '@angular/material/table';

@Component({
  selector: 'app-root',
  imports: [RouterOutlet, MatTableModule],
  templateUrl: './app.html',
  styleUrl: './app.scss'
})
export class App {

  columnas: string[] = ['nombre', 'precio', 'stock'];

  productos = [
    {nombre: 'Monitor Acer Nitro 23.8"', precio: 89.99, stock: 12},
    {nombre: 'Teclado mecánico', precio: 49.90, stock: 0},
    {nombre: 'Ratón inalámbrico', precio: 19.95, stock: 34},
  ];

}

  • En el HTML se define cada columna y luego las filas:

<table mat-table [dataSource]="productos">

  <ng-container matColumnDef="nombre">
    <th mat-header-cell *matHeaderCellDef>Nombre</th>
    <td mat-cell *matCellDef="let producto">{{producto.nombre}}</td>
  </ng-container>

  <ng-container matColumnDef="precio">
    <th mat-header-cell *matHeaderCellDef>Precio</th>
    <td mat-cell *matCellDef="let producto">{{producto.precio}}</td>
  </ng-container>

  <ng-container matColumnDef="stock">
    <th mat-header-cell *matHeaderCellDef>Stock</th>
    <td mat-cell *matCellDef="let producto">{{producto.stock}}</td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="columnas"></tr>
  <tr mat-row *matRowDef="let fila; columns: columnas;"></tr>
</table>

Las piezas son:

  • [dataSource]: El array con los datos. Cada elemento es una fila.
  • matColumnDef: Define una columna con un nombre. Dentro van su cabecera (mat-header-cell) y su celda (mat-cell).
  • *matCellDef="let producto": producto es el elemento del array de esa fila.
  • *matHeaderRowDef y *matRowDef: Las columnas que se muestran y en qué orden. Es el array columnas del .ts.
Para no mostrar una columna o cambiar el orden no hay que tocar las ng-container, solo el array columnas.

Más información: Table

Límites de tamaño (budgets)

ng serve no comprueba el tamaño de la aplicación, pero ng build sí: compila para producción y comprueba los budgets de angular.json. Si se pasa del límite de error, el build falla y no genera nada. La aplicación que funcionaba con ng serve no se puede desplegar, por ejemplo con el ng build del Dockerfile de Docker en el proyecto.

Cómo se usa ng build está en Automatización del proyecto.

Los límites que trae un proyecto nuevo son:

"budgets": [
  {
    "type": "initial",
    "maximumWarning": "500kB",
    "maximumError": "1MB"
  },
  {
    "type": "anyComponentStyle",
    "maximumWarning": "4kB",
    "maximumError": "8kB"
  }
]

  • initial: Lo que descarga el navegador al abrir la aplicación. Con Angular Material ya se pasa de 500kB, pero es solo un warning y el build termina bien. Es normal y se deja así:

▲ [WARNING] bundle initial exceeded maximum budget. Budget 500.00 kB was not met by 8.78 kB with a total of 508.78 kB.

  • anyComponentStyle: El CSS de cada componente, ya compilado de SASS. Este es el que rompe: a partir de 8kB es un error.

✘ [ERROR] src/app/features/productos/pages/productos/productos.scss exceeded maximum budget. Budget 8.00 kB was not met by 3.04 kB with a total of 11.04 kB.

Un mat.theme en el .scss de un componente ya son casi 8kB de CSS, porque genera todos los System Tokens; con dos, el build falla. Los temas van siempre en src/styles.scss, que no tiene límite por componente. No subas el maximumError para quitar el error: mueve el tema a styles.scss.

Ejercicios

Ejercicio 1

Crea una página de una tienda que tenga:

  • Una tabla con al menos 5 productos y las columnas nombre, precio y stock.
  • Debajo, una card por cada uno de 3 productos destacados con imagen, nombre, precio y los botones "Comprar" (relleno) y "Ver detalles" (solo texto).
  • Unas tabs con "Descripción", "Especificaciones" y "Opiniones".
clase/daw/diw/angular-material.1792875176.txt.gz · Última modificación: por claude