Skip to content

GitLab

  • Menu
Projects Groups Snippets
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • A angular
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 0
    • Issues 0
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Monitor
    • Monitor
    • Metrics
    • Incidents
  • Packages & Registries
    • Packages & Registries
    • Package Registry
    • Infrastructure Registry
  • Analytics
    • Analytics
    • CI/CD
    • Repository
    • Value stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • imunnic
  • angular
  • Wiki
  • Modulo 5

Modulo 5 · Changes

Page history
born authored Dec 22, 2025 by imunnic's avatar imunnic
Hide whitespace changes
Inline Side-by-side
Showing with 176 additions and 0 deletions
+176 -0
  • Modulo-5.md Modulo-5.md +176 -0
  • No files found.
Modulo-5.md 0 → 100644
View page @ 6ca55ed1
# **Gestión de Estado en Angular con Signals usando ResourceService**
## Introducción
En Angular moderno, los _Signals_ permiten implementar un **store reactivo** de manera nativa, sin librerías externas. Un _Signal_ mantiene un valor interno y notifica automáticamente a todos los componentes y funciones que dependen de él cuando cambia. Esto hace que la gestión de estado sea **simple, predecible y eficiente**, especialmente para aplicaciones que requieren compartir datos entre múltiples componentes.
La ventaja de Signals frente a otros enfoques es que la **reactividad está integrada en el framework**, sin necesidad de `subscribe()`, observables intermedios o memorias que limpiar. Esto permite que los componentes solo consuman datos y reaccionen automáticamente a los cambios del estado.
---
## Conceptos Clave
1. **Signal:** Contenedor de un valor reactivo que puede actualizarse mediante `.set()` o `.update()`.
2. **Computed:** Función derivada que calcula valores basados en Signals, actualizándose automáticamente cuando alguno de los Signals que depende cambian.
3. **Reactividad automática:** Los componentes que usan Signals se actualizan sin suscripciones explícitas.
4. **Inmutabilidad opcional:** Aunque los valores pueden mutar, es recomendable actualizar el Signal creando un nuevo estado para mantener consistencia y evitar efectos secundarios.
---
## Store con Signals y ResourceService
```ts
import { Injectable, signal, computed } from '@angular/core';
import { ResourceService } from './resource.service';
import { Resource } from './resource.model';
@Injectable({ providedIn: 'root' })
export class ResourceStore {
// Estado principal
private resourcesSignal = signal<Resource[]>([]);
// Selector derivado: número total de recursos
readonly resourceCount = computed(() => this.resourcesSignal().length);
// Selector derivado: filtrar recursos por nombre
filterResources(name: string) {
return computed(() => this.resourcesSignal().filter((r) => r.name.includes(name)));
}
constructor(private resourceService: ResourceService) {}
// Cargar recursos desde el servicio
loadResources() {
const resources = this.resourceService.get(); // Devuelve Resource[]
this.resourcesSignal.set(resources);
}
// Añadir un recurso
addResource(resource: Resource) {
this.resourcesSignal.update((current) => [...current, resource]);
}
// Eliminar un recurso por id
removeResource(id: number) {
this.resourcesSignal.update((current) => current.filter((r) => r.id !== id));
}
// Actualizar un recurso
updateResource(updated: Resource) {
this.resourcesSignal.update((current) =>
current.map((r) => (r.id === updated.id ? updated : r))
);
}
}
```
---
## Componente que usa la store
```ts
import { Component, OnInit } from '@angular/core';
import { ResourceStore } from './resource.store';
@Component({
selector: 'app-resource-list',
templateUrl: './resource-list.component.html',
})
export class ResourceListComponent implements OnInit {
newName = '';
constructor(public store: ResourceStore) {}
ngOnInit() {
// Cargar datos iniciales desde ResourceService
this.store.loadResources();
}
add() {
if (this.newName.trim()) {
const newResource = { id: Date.now(), name: this.newName };
this.store.addResource(newResource);
this.newName = '';
}
}
remove(id: number) {
this.store.removeResource(id);
}
}
```
---
## Template separado: `resource-list.component.html`
```html
<h2>Recursos ({{ store.resourceCount()() }})</h2>
<ul>
<li *ngFor="let resource of store.resources()">
{{ resource.name }}
<button (click)="remove(resource.id)">Eliminar</button>
</li>
</ul>
<input [(ngModel)]="newName" placeholder="Nombre del recurso" />
<button (click)="add()">Añadir Recurso</button>
```
**Notas importantes:**
1. `store.resources()` y `store.resourceCount()` se llaman como funciones porque son Signals / computed.
2. La carga de datos se realiza mediante `ResourceService.get()`, manteniendo la separación entre obtención de datos y gestión del estado.
3. Toda la lógica de estado (añadir, eliminar, actualizar) permanece centralizada en el store, dejando los componentes limpios y enfocados en la presentación.
4. La reactividad es automática: al actualizar `resourcesSignal`, el template se refresca sin necesidad de `subscribe()`.
---
## Selectores Computados
Los _computed_ permiten derivar información del estado principal de manera reactiva:
```ts
// Filtrar recursos cuyo nombre contiene "Angular"
readonly angularResources = computed(() =>
this.resourcesSignal().filter(r => r.name.includes('Angular'))
);
// Contar recursos con un nombre específico
countResourcesByName(name: string) {
return computed(() => this.resourcesSignal().filter(r => r.name === name).length);
}
```
Uso en el template:
```html
<div>Total Angular Resources: {{ store.countResourcesByName('Angular')() }}</div>
```
---
## Efectos y reactividad adicional
Si se desea reaccionar automáticamente a cambios del estado:
```ts
import { effect } from '@angular/core';
effect(() => {
console.log('Número de recursos:', this.store.resourceCount());
});
```
Cada vez que cambie `resourceCount`, se ejecutará la función del effect. Es útil para sincronizaciones externas, registros de auditoría o cálculos derivados.
---
## Buenas Prácticas
1. Mantener el estado inmutable: actualizar arrays y objetos creando nuevas instancias.
2. Usar `computed` para todos los valores derivados.
3. Separar la lógica de estado de los componentes: el store maneja la manipulación de datos y los componentes solo consumen y disparan acciones.
4. Usar efectos (`effect()`) únicamente para side effects, nunca para mutar el estado principal.
---
Clone repository

Índice

  • Inicio
  • Módulo 1. Fundamentos y arranque del proyecto
    • Módulo 1.1 Angular
    • Módulo 1.2 Estructura
    • Módulo 1.2 Arquitectura y conceptos base
  • Módulo 2. Componentes y reutilización
  • Módulo 3. Navegación y estructura de aplicación
  • Módulo 4. Servicios y comunicación con backend
  • Módulo 5. Gestión de estado (Stores)
  • Módulo 6. Calidad, optimización y cierre