Módulo 2 – Componentes en Angular
En Angular, los componentes son la unidad fundamental para construir la interfaz de usuario. Cada componente encapsula una parte de la aplicación, combinando lógica, vista y estilos. Este bloque profundiza en cómo diseñar, reutilizar y comunicar componentes, así como en la integración de librerías externas dentro de la aplicación Panacea, orientada a la gestión de recursos sanitarios.
Sesión 5 – Primer componente: vista principal
Introducción teórica
Un componente representa una sección concreta de la interfaz de usuario. Puede entenderse como un bloque autónomo que controla qué se muestra y cómo se comporta una parte de la aplicación. En Angular, toda aplicación se construye a partir de componentes organizados de forma jerárquica.
En esta sesión se crea el primer componente funcional de Panacea, que actúa como vista principal y punto de entrada visual de la aplicación.
Creación con Angular CLI
ng generate component pages/dashboard
Estructura de un componente
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent {
titulo = 'Panel de recursos sanitarios';
}
Separación de lógica y vista
La clase del componente contiene la lógica y los datos, mientras que la plantilla HTML se limita a representar esa información.
export class DashboardComponent {
recursos = [
{ id: 1, codigo: 'REC-01', tipo: 'Ambulancia', estado: 'Disponible' },
{ id: 2, codigo: 'REC-02', tipo: 'Helicóptero', estado: 'En servicio' }
];
}
<h1>{{ titulo }}</h1>
<ul>
@for (recurso of recursos; track recurso){
<li >
{{ recurso.codigo }} - {{ recurso.tipo }} - {{ recurso.estado }}
</li>
}
</ul>
Estilos por componente
h1 {
color: #2c3e50;
}
Sesión 6 – Componentes reutilizables
Introducción teórica
La reutilización de componentes permite construir aplicaciones más mantenibles y escalables. Cuando una parte de la interfaz se repite o tiene una responsabilidad clara, debe convertirse en un componente reutilizable. Esto reduce duplicación, facilita cambios y mejora la legibilidad del código.
Componente reutilizable: cabecera
ng generate component layout/header
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent {
appName = 'Panacea';
}
<header>
<h2>{{ appName }}</h2>
<span>Sistema de gestión de recursos sanitarios</span>
</header>
Uso del componente en una vista
<app-header></app-header>
<app-dashboard></app-dashboard>
Encapsulación de estilos
header {
background-color: #e3f2fd;
padding: 1rem;
}
Sesión 7 – Comunicación entre componentes (Inputs)
Introducción teórica
Los parámetros de entrada permiten enviar datos desde un componente padre a un componente hijo. En Angular, esto se realiza mediante el decorador @Input().
Conceptualmente, un @Input() puede compararse con un parámetro de un constructor: define qué información necesita un componente para funcionar correctamente, pero sin controlar cómo se crea.
Componente listado de recursos
ng generate component recursos/resource-list
export class ResourceListComponent {
@Input() recursos: any[] = [];
}
Paso de datos desde el componente padre
export class DashboardComponent {
recursos = [
{ id: 1, codigo: 'REC-01', tipo: 'Ambulancia', estado: 'Disponible' },
{ id: 2, codigo: 'REC-02', tipo: 'Helicóptero', estado: 'En servicio' }
];
}
<app-resource-list [recursos]="recursos"></app-resource-list>
<ul>
<li *ngFor="let recurso of recursos">
{{ recurso.codigo }} - {{ recurso.tipo }} - {{ recurso.estado }}
</li>
</ul>
Sesión 8 – Comunicación entre componentes (Outputs)
Introducción teórica
Los eventos permiten que un componente hijo notifique acciones al componente padre. En Angular, esto se gestiona mediante @Output() y EventEmitter.
Mientras que los @Input() reciben datos, los @Output() emiten eventos, permitiendo una comunicación clara y desacoplada entre componentes.
Componente recurso individual
ng generate component recursos/resource-item
export class ResourceItemComponent {
@Input() recurso: any;
@Output() seleccionar = new EventEmitter<any>();
onClick() {
this.seleccionar.emit(this.recurso);
}
}
<div (click)="onClick()">
{{ recurso.codigo }} - {{ recurso.tipo }} - {{ recurso.estado }}
</div>
Captura del evento en el padre
<app-resource-item
*ngFor="let rec of recursos"
[recurso]="rec"
(seleccionar)="mostrarDetalle($event)">
</app-resource-item>
mostrarDetalle(recurso: any) {
this.recursoSeleccionado = recurso;
this.mostrarModal = true;
}
Sesión 9 – Ciclo de vida de los componentes
Introducción teórica
El ciclo de vida de un componente describe las distintas fases por las que pasa desde que se crea hasta que se destruye. Angular expone estos momentos mediante métodos llamados hooks, que permiten ejecutar lógica en instantes concretos.
ngOnInit
Se utiliza para inicializar datos.
export class DashboardComponent implements OnInit {
ngOnInit() {
console.log('Vista principal inicializada');
}
}
ngOnChanges
Se ejecuta cuando cambian los valores recibidos por @Input().
export class ResourceListComponent implements OnChanges {
@Input() recursos: any[] = [];
ngOnChanges() {
console.log('Listado de recursos actualizado');
}
}
ngOnDestroy
Permite limpiar recursos antes de que el componente desaparezca.
export class ResourceItemComponent implements OnDestroy {
ngOnDestroy() {
console.log('Componente de recurso destruido');
}
}
Sesión 10 – Importación de librerías externas (PrimeNG)
Introducción teórica
Las librerías externas amplían las capacidades de Angular ofreciendo componentes, utilidades o estilos ya implementados. Su uso permite acelerar el desarrollo y mantener una interfaz consistente.
La documentación oficial de cada librería es siempre la principal fuente de referencia y suele encontrarse en su sitio web o repositorio oficial.
Instalación de PrimeNG
npm install primeng primeicons
Importación de un módulo
import { DialogModule } from 'primeng/dialog';
@NgModule({
imports: [
DialogModule
]
})
export class AppModule {}
Uso de un componente PrimeNG (modal)
<p-dialog
header="Detalle del recurso"
[(visible)]="mostrarModal"
[modal]="true">
<div *ngIf="recursoSeleccionado">
<p>Código: {{ recursoSeleccionado.codigo }}</p>
<p>Tipo: {{ recursoSeleccionado.tipo }}</p>
<p>Estado: {{ recursoSeleccionado.estado }}</p>
</div>
</p-dialog>
mostrarModal = false;
recursoSeleccionado: any = null;