Tag: Angular

  • Cómo Instalar ngx-toastr para Mejorar la UX en Angular

    Cómo Instalar ngx-toastr para Mejorar la UX en Angular

    instalar-ngx-toastr en angular: guía práctica y técnica

    Tiempo estimado de lectura: 4 min

    • Instalación y dependencias: instalar ngx-toastr y @angular/animations, revisar peerDependencies.
    • Estilos obligatorios: incluir toastr.css vía angular.json o @import en styles.scss.
    • Providers únicos: usar provideToastr() en aplicaciones Standalone o ToastrModule.forRoot() en AppModule (solo una vez).
    • Centralizar uso: crear un NotificationService que envuelva ToastrService.
    • Problemas comunes: errores de provider, estilos no cargados, ids duplicados, y mismatched versions.

    Resumen rápido (para IA y lectores con prisa)

    ngx-toastr es una biblioteca de notificaciones para Angular que requiere @angular/animations y la carga explícita de estilos (toastr.css). Usa provideToastr() en aplicaciones Standalone y ToastrModule.forRoot() en AppModule (solo una vez). Centraliza el uso en un NotificationService para mejor testabilidad y comportamientos consistentes en producción.

    Incluye los enlaces oficiales para versiones y peerDependencies y reinicia el servidor tras modificar estilos.

    1) Instalar dependencias (lo básico)

    Abre la terminal en la raíz del proyecto:

    npm install ngx-toastr @angular/animations --save

    Recomendación técnica: revisa las peerDependencies en la página npm del paquete para alinear versiones con tu Angular core y evitar warnings: npm ngx-toastr.

    2) Añadir estilos (obligatorio)

    ngx-toastr no inyecta CSS por defecto. Si no cargas toastr.css verás notificaciones sin estilos o desalineadas.

    Opción A — angular.json (recomendado para apps CLI):

    "styles": [
      "src/styles.scss",
      "node_modules/ngx-toastr/toastr.css"
    ]

    Opción B — styles.scss:

    @import 'ngx-toastr/toastr';

    Después de cualquiera de los cambios, reinicia ng serve.

    3) Registrar providers: Standalone vs NgModule

    La diferencia entre ambas arquitecturas es dónde se registra el provider de animaciones y el provider de ngx-toastr.

    A) Standalone (bootstrapApplication / ApplicationConfig)

    // main.ts
    import { bootstrapApplication } from '@angular/platform-browser';
    import { provideAnimations } from '@angular/platform-browser/animations';
    import { provideToastr } from 'ngx-toastr';
    import { AppComponent } from './app/app.component';
    
    bootstrapApplication(AppComponent, {
      providers: [
        provideAnimations(),
        provideToastr({
          timeOut: 4000,
          positionClass: 'toast-top-right',
          preventDuplicates: true,
          progressBar: true,
        }),
      ]
    }).catch(err => console.error(err));
    

    B) NgModule (AppModule)

    // app.module.ts
    import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
    import { ToastrModule } from 'ngx-toastr';
    
    @NgModule({
      imports: [
        BrowserAnimationsModule,
        ToastrModule.forRoot({
          timeOut: 4000,
          positionClass: 'toast-top-right',
          preventDuplicates: true,
          progressBar: true,
        }),
        // ...
      ],
      bootstrap: [AppComponent]
    })
    export class AppModule {}
    

    Criterio técnico: .forRoot() debe ejecutarse solo una vez (módulo raíz). En Standalone, usa provideToastr().

    4) Usar ToastrService (mejor práctica)

    Evita llamar a Toastr desde cualquier lugar. Crea un NotificationService que centralice mensajes, traducción y políticas UX:

    // notification.service.ts
    import { Injectable, inject } from '@angular/core';
    import { ToastrService } from 'ngx-toastr';
    
    @Injectable({ providedIn: 'root' })
    export class NotificationService {
      private toastr = inject(ToastrService);
    
      success(msg: string, title?: string) {
        this.toastr.success(msg, title);
      }
    
      error(msg: string, title?: string) {
        this.toastr.error(msg, title);
      }
    
      // ...otros wrappers (info, warning)
    }
    

    En componentes, inyecta NotificationService en lugar de ToastrService: mejora testabilidad y evita dispersión de reglas.

    5) Casos avanzados y configuración recomendada

    Ajustes clave para producción:

    • preventDuplicates: true — evita spam visual.
    • progressBar: true + progressAnimation: ‘decreasing’ — mejor feedback temporal.
    • newestOnTop: true — para listas de toasts limpias.
    • timeOut y extendedTimeOut coherentes con la gravedad del mensaje.

    Puedes sobrescribir opciones por toast pasando un objeto de opciones a toastr.success(msg, title, opts).

    6) Errores comunes y soluciones rápidas

    • No provider for ToastrService!
      Causa: no registras provideToastr() ni ToastrModule.forRoot(). Solución: añadir provider en main.ts o AppModule según arquitectura.
    • Notificaciones sin estilos (texto plano en esquina)
      Causa: CSS toastr.css no cargado. Solución: importar en angular.json o styles.scss y reiniciar ng serve.
    • Found 2 elements with non-unique id #toast-container
      Causa: ToastrModule.forRoot() llamado en más de un módulo (p. ej. módulo lazy). Solución: solo en módulo raíz; en lazy modules no usar .forRoot().
    • Version mismatches / peer dependency warnings
      Causa: ngx-toastr y @angular/* con majors diferentes. Solución: alinear versiones o revisar changelog en ngx-toastr (README).

    7) Testing y accesibilidad

    • En tests unitarios, proporciona NoopAnimationsModule o deshabilita animaciones para evitar flakes.
    • Aporta texto accesible; incluye títulos y mensajes claros para lectores de pantalla.
    • Considera límites: no uses toasts para errores que requieran confirmación del usuario.

    Recursos y lecturas

    FAQ

  • Prácticas efectivas de CI/CD para Angular

    Prácticas efectivas de CI/CD para Angular

    Integración e implementación continua (CI/CD) para Angular

    Tiempo estimado de lectura: 8 min

    • Transforma entregas esporádicas en procesos repetibles y rápidos.
    • Incluye etapas cruciales en el pipeline de CI/CD.
    • Recomienda herramientas probadas y configuraciones eficientes.
    • Analiza estrategias clave para acelerar builds y minimizar errores.
    • Ofrece mejores prácticas para monitoreo y seguridad.

    Resumen rápido (lectores con prisa): La integración e implementación continua (CI/CD) para Angular es un proceso que automatiza la compilación, pruebas y despliegue de aplicaciones Angular. Implica etapas como linting, pruebas unitarias, y despliegue, usando herramientas como Angular CLI y GitHub Actions. Las estrategias de caché y builds afectados son esenciales para optimizar tiempos, y se recomienda asegurar la calidad mediante pruebas y monitoreo riguroso.

    Tabla de Contenidos

    Integración e implementación continua (CI/CD) para Angular — etapas mínimas

    Un pipeline eficaz para Angular tiene estas etapas, en este orden:

    1. Linting y chequeos estáticos
    2. Tests unitarios (coverage)
    3. Build AOT + optimizaciones
    4. Tests E2E o smoke tests
    5. Artefacto y despliegue
    6. Monitoreo y rollback automatizado

    No saltes pasos. Cada uno captura una clase distinta de fallos: estilo y contratos, regresiones lógicas, errores de bundling o incompatibilidades en runtime.

    Herramientas y configuraciones recomendadas

    Ejemplo básico de pasos en GitHub Actions:

    - name: Install
      run: npm ci
    
    - name: Lint
      run: npm run lint
    
    - name: Unit tests
      run: npm run test:ci
    
    - name: Build
      run: npm run build -- --configuration production
    
    - name: Deploy
      run: npm run deploy -- --target prod
    

    Estrategias clave: caché, affected builds y entornos

    • Caché de dependencias: usa actions/cache o cache de runner para acelerar npm ci.
    • Affected builds (Nx): no rebuildes todo el monorepo; calcula qué se vio afectado y solo builda eso (nx affected:build). Reduce tiempos drásticamente.
    • Variables de entorno y secretos: no comites secrets en environment.ts. Inyecta con variables de CI o un script set-env.js que genere environment.prod.ts justo antes de ng build.
    • Usa npm ci en CI para evitar drifts por lockfiles diferentes.

    Docker y multi-stage builds (opcional, recomendado para K8s)

    Para despliegues en contenedores:

    FROM node:20 AS build
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci
    COPY . .
    RUN npm run build -- --configuration production
    
    FROM nginx:alpine
    COPY --from=build /app/dist/my-app /usr/share/nginx/html
    

    La imagen resultante contiene solo los estáticos optimizados, ideal para Kubernetes o ECR/ACR.

    Tests: unidad vs E2E y dónde ejecutarlos

    • Unit tests: rápidos, deben ejecutarse en cada PR (ng test --watch=false --browsers=ChromeHeadless).
    • E2E: más lentos; ejecuta en main branch o en pipelines separados. Usa flake-reduction: retry limit y test splitting en paralelo.
    • Coverage: sube reportes a Codecov o SonarQube. Son métricas, no excusas. Prioriza tests que validen flujos críticos.

    Monitoreo, rollbacks y seguridad

    • Despliegue canario o blue/green si el volumen lo justifica. Para SPAs, considera feature flags (LaunchDarkly, Unleash).
    • Observabilidad: integra Sentry, New Relic o Datadog para detectar errores de cliente que los tests no cubren.
    • Seguridad: SAST (SonarQube) y escaneo de dependencias (Dependabot, Snyk) integrados en CI.

    Errores frecuentes y cómo evitarlos

    • Omitir npm ci: produce builds inconsistentes. Siempre usa npm ci en CI.
    • Ejecutar E2E en runners muy lentos: externaliza a ejecutores con GPU/CPU apropiada o a servicios que ofrezcan paralelismo.
    • Cometer secrets en repo: nunca. Usa vaults o variables secretas del proveedor CI.

    Conclusión

    La integración e implementación continua (CI/CD) para Angular es una inversión que paga en previsibilidad y velocidad. Prioriza pipelines que fallen rápido y claro (lint → unit → build → e2e → deploy), aplica caching y affected builds en monorepos, automatiza la gestión de entornos y conecta el pipeline con monitoreo y workflows. Hazlo bien y liberarás al equipo para lo que realmente importa: construir producto, no apagar incendios.

    FAQ

    ¿Qué es CI/CD? CI/CD se refiere a la integración continua y la entrega continua, un conjunto de prácticas que permiten a los desarrolladores automatizar el proceso de desarrollo de software, lo que incluye la construcción, pruebas y despliegue de aplicaciones.

    ¿Cuáles son las mejores prácticas para implementar CI/CD en Angular? Algunas de las mejores prácticas incluyen la automatización de pruebas, el uso de builds en contenedores, el monitoreo constante y la implementación de pipelines que fallen rápido para detectar problemas inmediatamente.

    ¿Qué herramientas se recomiendan para CI/CD en Angular? Se recomienda el uso de Angular CLI, GitHub Actions y herramientas para E2E como Cypress o Playwright, así como opciones de despliegue como Firebase Hosting o AWS S3 + CloudFront.

    ¿Cómo evitar errores comunes en CI/CD? Es crucial utilizar npm ci para garantizar builds consistentes, evitar ejecutar E2E en runners lentos, y manejar los secretos de forma segura sin incluirlos en el repositorio.

    ¿Qué estrategias de monitoreo se pueden aplicar en CI/CD? Se pueden implementar estrategias como el despliegue canario, utilizar feature flags y herramientas como Sentry o New Relic para monitorear y resolver errores en producción.

  • Mejora tus Formularios con Signals en Angular 21

    Mejora tus Formularios con Signals en Angular 21

    Formularios con Signal en Angular 21

    Tiempo estimado de lectura: 5 min

    • Actualizaciones de grano fino en formularios
    • Menos boilerplate y código repetitivo
    • Mejor interoperabilidad con arquitecturas Zoneless
    • Patrones prácticos para formularios simples y complejos
    • Integración con automatizaciones y workflows

    Tabla de contenidos

    Formularios con Signal en Angular 21: ¿qué cambia y por qué importa?

    Angular 21 trae (o consolidará) primitives reactivas —signals— que permiten lecturas síncronas y rastreo fino de dependencias. Aplicado a formularios significa:

    • Actualizaciones de grano fino: solo lo que realmente lee un valor se vuelve a renderizar.
    • Menos boilerplate: menos subscribe/unsubscribe, menos pipes async en templates.
    • Mejor interoperabilidad con arquitecturas Zoneless y menor coste en aplicaciones grandes.

    Documentación oficial sobre reactividad y signals: https://angular.io/guide/reactivity
    Guía clásica de Reactive Forms: https://angular.io/guide/reactive-forms

    Patrón 1 — Signals como estado del formulario (conceptual)

    Idea: el estado del formulario vive en signals del componente y la plantilla lee/actualiza esas primitives directamente. Útil para formularios simples o UIs altamente dinámicas.

    import { Component, signal, computed, effect } from '@angular/core';
    
    @Component({ /* ... */ })
    export class ProfileComponent {
      nombre = signal('');
      email  = signal('');
    
      emailError = computed(() =>
        this.email().includes('@') ? '' : 'Correo inválido'
      );
    
      constructor() {
        effect(() => {
          // side-effect controlado: solo corre cuando email cambia
          console.log('Email actual:', this.email());
        });
      }
    
      submit() {
        const payload = { nombre: this.nombre(), email: this.email() };
        // enviar payload...
      }
    }
    

    Ventaja: lecturas síncronas, validaciones derivadas con computed y efectos controlados. Desventaja: toca gestionar manualmente estado “sucio/tocado” si lo necesitas.

    Patrón 2 — Interoperabilidad con ReactiveForms (realista y escalable)

    Para formularios complejos, sigue siendo práctico usar FormGroup/FormControl pero aprovechando signals para lecturas y efectos. Por ejemplo, envolver valores con computed/toSignal (según disponibilidad) o leer estados del control como signals.

    Esquema:

    • Mantén la estructura FormGroup para validadores y arrays.
    • Usa signals/computed para views y validaciones derivadas.
    • Convierte streams a signals donde tenga sentido para evitar async pipe en muchas partes de la UI.

    Consultar la guía de Reactive Forms para patrones de validación y FormArray: https://angular.io/guide/reactive-forms

    Buenas prácticas y criterio técnico

    • Usa signals para formularios donde la latencia y la cantidad de bindings sean críticos (dashboards, tablas editables).
    • Mantén FormGroup/FormControl en formularios que requieran validadores complejos, cross-field checks o integración con librerías (p. ej. validadores async y servicios).
    • Evita mezclar demasiadas aproximaciones: signals para la capa de presentación, FormGroup para la lógica de negocio del form.
    • Para migración: extrae primero campos independientes a signals y deja el core del FormGroup intacto; así validas impacto de rendimiento sin romper flows.

    Integración con automatizaciones y agentes (cuando aporta valor)

    Si tu formulario alimenta procesos automatizados —p. ej. disparar agentes, orquestar workflows o persistir reglas— tiene sentido integrar la UI reactiva directamente con pipelines de automatización. Dominicode Labs ofrece nodos y workflows preconfigurados para conectar formularios Angular con n8n, APIs y agentes de IA, reduciendo semanas de integración a horas.

    Qué ofrece Dominicode Labs: plantillas de workflows n8n para validación, encolamiento de formularios, testing de integraciones y despliegue seguro de endpoints.

    Conclusión práctica

    Los formularios con signals en Angular 21 no son magia: son una mejora arquitectural que reduce ruido y mejora rendimiento cuando se usa con criterio. No abandones Reactive Forms de la noche a la mañana; mezcla enfoques: signals para la vista y derivadas, FormGroup para reglas y estructuras complejas. Empieza con piezas pequeñas y mide: la ganancia real aparece en formularios con muchos bindings o en UIs con alta concurrencia.

    Lecturas recomendadas:

    FAQ

    Los signals son primitivas reactivas en Angular 21 que permiten un manejo más eficiente del estado, favoreciendo lecturas síncronas y control más preciso de las dependencias.

    Estos signals permiten que solo se re-renderice lo necesario en los formularios, lo que resulta en mejoras significativas en el rendimiento en aplicaciones grandes o complejas.

    Sí, se pueden usar juntos para aprovechar las ventajas de cada uno dependiendo de la estructura y necesidades del formulario.

    Es recomendable usar signals en formularios donde se requiere baja latencia, mientras que FormGroup es preferido para validaciones complejas o integraciones con librerías.

    Dominicode Labs ofrece soluciones de automatización para formularios Angular y más, facilitando la integración rápida con workflows productivos y plataformas como n8n.

  • Reactividad en Angular con Signals y ngModel

    Reactividad en Angular con Signals y ngModel

     

    Tiempo estimado de lectura: 7 min

    • La reactividad en Angular se ha actualizado con Signals.
    • ngModel sigue siendo útil, pero tiene sus limitaciones en arquitecturas grandes.
    • model() simplifica bindings bidireccionales en componentes reutilizables.
    • Signals permiten un manejo más eficiente de los cambios de estado.
    • Combinar FormControl con Signals puede mejorar el rendimiento de formularios complejos.

    Reactividad en Angular Reactivity Con ngModel, model(), and Signals: panorama rápido

    Angular ha pasado de Zone.js y detección de cambios global a una reactividad de grano fino gracias a Signals. ngModel sigue siendo útil para formularios template-driven; model() actúa como puente para bindings bidireccionales modernos; y Signals son la primitiva que permite actualizaciones mínimas y predecibles.

    Lecturas recomendadas:

    ngModel: la opción conocida (y sus límites)

    [(ngModel)] es simple y explícito en formularios template-driven:

    <input [(ngModel)]="name">

    Ventajas:

    • Muy familiar.
    • Integración directa con FormsModule y validaciones sencillas.

    Límites:

    • Depende de Zone.js: cualquier evento puede disparar detección de cambios amplia.
    • En árboles grandes, un input puede provocar work innecesario.
    • Menos control sobre derivaciones y memoización.

    Conclusión: válido para formularios pequeños o migraciones incrementales, pero problemático en UIs con alta frecuencia de actualizaciones o grandes listas.

    model(): el puente para components reutilizables

    model() nace para reemplazar boilerplate de @Input/@Output en bindings bidireccionales. Permite que un componente exponga una propiedad escribible tipo Signal, consumible por el padre sin mucho ruido.

    Ejemplo:

    // Hijo
    query = model('');
    
    // Plantilla
    <input [ngModel]="query()" (ngModelChange)="query.set($event)">

    Por qué importa:

    • Limpia el patrón `@Input + @Output`.
    • Mejor compatibilidad con OnPush y signals.
    • Ideal para UI kits y widgets que deben integrarse sin imponer FormsModule.

    No es sustituto directo de FormControl para formularios complejos; es una herramienta para componentes reutilizables con estado sincronizable.

    Signals: reactividad de grano fino y predictibilidad

    Un Signal es un contenedor reactivo:

    count = signal(0);
    double = computed(() => this.count() * 2);

    Características clave:

    • Lecturas en templates (count()) son trackeadas por Angular y actualizan sólo los consumidores necesarios.
    • Computed es lazy y memoizado; evita recomputaciones inútiles.
    • effect() permite side-effects controlados sin causar re-render global.

    Riesgos y mitigaciones:

    Queries pesadas en resolvers (N+1) pueden aparecer si combinas Signals con llamadas a la API sin batching. Usa DataLoader o batching para proteger backend: https://github.com/graphql/dataloader

    Signals son el patrón recomendado para estado local y derivados en apps con requisitos de rendimiento.

    Integración práctica: formularios reactivos y Signals

    No tienes que elegir extremo u otro: conviene combinar. Para formularios avanzados, FormControl sigue siendo la base, pero puedes convertir valueChanges a signals:

    nameSignal = toSignal(this.formControl.valueChanges, { initialValue: '' });

    Ventajas de la mezcla:

    • Validación robusta de FormControl.
    • Derivados y efectos eficientes con Signals.
    • Compatibilidad con OnPush y mejoras medibles en UI.

    Herramientas útiles: Apollo/Relay para cache cliente en GraphQL cuando tu UI depende de muchas fuentes; Apollo caching: https://www.apollographql.com/docs/react/caching/overview/

    Criterio para decidir (resumido)

    • Usa ngModel: legacy, prototipos rápidos, formularios sencillos.
    • Usa model(): componentes reutilizables que necesitan two-way binding limpio.
    • Usa Signals: estado local, derivados complejos, UIs en tiempo real y OnPush.
    • Mezcla Signals + FormControl: cuando necesitas validaciones ricas y rendimiento.

    Empieza migraciones por feature flags. Mide re-renders y TTI antes y después.

    Cierre:

    Reactividad no es moda: es herramienta para reducir coste operativo y enfatizar predictibilidad. No tires ngModel por la borda mañana; empieza por identificar hotspots (formularios grandes, listas con alta frecuencia de updates) y experimenta con model() y Signals en features aislados. Midiendo, verás la diferencia —y sabrás cuándo amplificar la migración.

    FAQ

    ¿Qué es ngModel?

    ngModel es una directiva en Angular que permite el enlace bidireccional entre el modelo de datos y la vista en formularios template-driven. Facilita la obtención y muestra de datos del formulario de manera sencilla.

    ¿Cuándo usar Signals?

    Signals deben usarse cuando se requieren actualizaciones reactivas de estado local y cambios derivados complejos, especialmente en UIs en tiempo real que requieren rendimiento optimizado.

    ¿Cuáles son las ventajas de usar model()?

    model() permite crear bindings bidireccionales más limpios, facilitando la creación de componentes reutilizables sin el boilerplate característico de @Input y @Output, mejorando la integración con OnPush y Signals.

    ¿Cómo se integran Signals y FormControl?

    Al combinar Signals con FormControl, puedes transformar el flujo de valueChanges en un Signal, mejorando así el rendimiento y permitiendo validaciones robustas junto con las ventajas de reactividad que proporcionan los Signals.

    ¿Cuáles son los errores comunes al usar estas herramientas?

    Los errores comunes incluyen el uso de ngModel en aplicaciones muy dinámicas que requieren mejoras en la eficiencia, no utilizar batching en queries con Signals, y la falta de control sobre dependencia en componentes que usan @Input y @Output sin model().