¿Por qué Angular?
- JavaScript, desde mi experiencia
- Web Components
- Programación reactiva (RxJS)
- Angular
- Simplicidad
- Rendimiento óptimo
- Ahead of Time Compilation
- Lazy Loading
- Inyección de dependencias y testing
- Mejoras en el SEO
- Integración con otras tecnologías
- Multi soporte a navegadores
- Internet de las cosas y la web física
- Conclusión
Entorno de desarrollo
- Instalación de las herramientas necesarias
- Git
- NodeJS y npm
- Angular CLI
- Editor de texto: Visual Studio Code
- Chrome
- Gestión del proyecto con Angular-Cli (v15.0.5)
- Creación del proyecto
- Ejecución de la aplicación en desarrollo
- Ejecución de los tests unitarios
- Ejecución de los tests de aceptación o e2e
- Creación de elementos
- Descubrimiento de errores de estilo y codificación
- Construcción del proyecto
- Acceder a la documentación
- Añadir funcionalidad
- Ayuda para el deploy de la aplicación
- Trabajar con la configuración del espacio de trabajo
- Actualizar las dependencias del proyecto
- Consejo para la ejecución de los comandos
- Configuración de la generación por defecto (Angular CLI 6+)
- El IDE no refresca los cambios automáticamente
- Estructura del proyecto y ficheros importantes
- Cambios en la configuración por defecto
- Cambio de Karma por Jest
- Cambio de Protractor por Cypress
Módulos
- @NgModule
- Creación de un módulo secundario
- Arranque de la aplicación automático
- Arranque manual de la aplicación
Directivas
- Componentes
- Directivas de atributo
- ngClass y class binding
- ngStyle y style binding
- Directivas estructurales
- ngIf
- ngIf - then - else
- ngSwitch
- ngFor
- Práctica
- Creación de una directiva de atributo propia
Pipes
- Pipes de serie
- Parametrización y encadenado
- Creación de pipes propios
Data Binding
- Interpolation
- Property binding
- Element Property
- Directive property
- Component Property
- Event binding
- NgModel
- Práctica: comunicación entre padre e hijo
Servicios e inyección de dependencias
- Elemento Injector
- Injector principal
- Injectores secundarios
- Localización de dependencias
- Declaración de providers
- useClass
- useValue
- useFactory
- Simplificación en la inyección
- Actualización a partir de Angular 6
Routing
- Configuración del router en el módulo principal
- Configuración del router en módulo secundario o de feature
- Configuración con Lazy Loading
- Para el módulo secundario o de feature
- Para el módulo principal
- Router outlet y router links
- Navegación desde código
- Recuperación de la información
- Query params
- Rutas de guarda
- CanActivate
- CanDeactivate
- Rutas anidadas
- Rutas auxiliares
- Resolución de información en el router
- Acceso a la información del router del padre
- Los 7 pasos del proceso de routing
- Ciclo de navegación y eventos del router
Formularios
- Configuración inicial
- Creación del formulario
- Configuración de los elementos del formulario
- Validaciones síncronas
- Validar campos relacionados
- Validaciones asíncronas
- Configuración de cuando disparar las validaciones
- Estados de un formulario
- Añadir dinámicamente un control
- Añadir dinámicamente un conjunto de controles
- Hacer que las validaciones se ejecuten en tiempo real
- Crear componentes con subformularios
Http: comunicación con servidor remoto
- Historia de la asincronía
- Callbacks
- Promesas
- Observables
- Servicio HttpClient
- Recuperación de datos
- Descarga de un fichero Excel
- Interceptores
- Modificar cabeceras
- Gestión del token y el token de refresco
- Logging
- Manejar errores
- Controlar peticiones a través de timeout
- Escucha de eventos de progreso
- Uso de async pipe con objetos
Testing
- Introducción
- Tests unitarios y de integración con Jasmine
- Test Suite
- Test Case
- Matchers
- beforeEach() y afterEach()
- Karma
- Arquitectura de una aplicación testeable
- Creación de fakes con Jasmine
- Tests unitarios con Mockito
- TestBed
- Situaciones de testing
- Test de un pipe / servicio sin dependencias
- Test de un pipe/servicio con dependencias
- Tests asíncronos
- Test de componente sin dependencias
- Test de componente con dependencias
- Test de navegación
- Test que involucran al Router
- Test de formularios
- Test de @Output (EventEmitter)
- Test de directiva
- Test de un servicio con dependencia HttpClient
- Tests de aceptación con Protractor
- Protractor
- Test de aceptación con Cypress
- Caso práctico
- Cambiar Protractor por Cypress
- Calcular la cobertura que genera Cypress
- Conclusión
Integraciones
- Integración con PrimeNG
- Instalación de PrimeNG en angular-cli
- Utilización de la librería
- Integración con StencilJS
- Empezando con StencilJS
- Creación del primer componente
- Elementos del API
- Métodos del ciclo de vida
- Uso para hacer layouts
- Internacionalización (i18n)
- Establecer tema de forma dinámica
- Integración con Storybook
Puesta en producción
- Análisis del tamaño de la aplicación
- Verifica que solo se incluye lo obligatorio
- Verifica el tamaño del bundle principal
- No subas los .map
- Genera la documentación
- Aplicar técnicas de optimización
- Entendiendo el “Browser rendering”
- Cómo mejorar el “Browser rendering”
- Técnicas de optimización en Angular
- Eliminación de espacios en blanco
- Uso de web workers
- Despliegue de la solución en nginx
- Empaquetado con Docker
Programación reactiva (RxJS)
- Conceptos básicos
- DataSource
- Observable
- Tipos de observables
- Formas de crear un Observable
- Subscriber
- Observer
- Subscription
- Operadores
- Buffering & Windowing
- buffer(obs)
- bufferCount(n)
- bufferTime(x)
- bufferTogle(opening, closing)
- bufferWhen(cond)
- window()
- windowCount(n)
- windowTime(n ms)
- windowToggle(opening, closing)
- windowWhen
- Manejo de errores
- catchError()
- throwIfEmpty
- retry
- retryWhen
- timeout
- timeoutWith
- Filtrado múltiple de resultados
- skip(n)
- skipLast(n)
- skipUntil()
- skipWhile(cond)
- take(n)
- takeLast(n)
- takeUntil(timer)
- takeWhile(cond)
- distinct
- distinctUntilChanged
- distinctUntilKeyChanged
- filter(cond)
- sample(timer)
- audit
- Ejemplo sample vs audit
- throttle
- Filtros de un solo valor
- first
- last
- min
- max
- elementAt(n)
- find(cond)
- findIndex(cond)
- single(cond)
- Combinando observables
- combineAll
- concatAll()
- exhaust()
- mergeAll()
- withLatestFrom(internal, internal, …)
- combineLatest([obs, obs, …])
- forkJoin([obs, obs, …])
- Agrupando valores
- groupBy
- pairwise
- partition(cond)
- switchAll()
- toArray()
- zipAll()
- Transformación de observables en nuevo observable
- repeat(n)
- repeatWhen(obs)
- ignoreElements
- finalize
- Multicasting
- shareReplay(n)
- Operadores de nivel superior
- concatMap()
- mergeMap()
- switchMap()
- exhaustMap()
- Tiempo, duración y planificación
- auditTime(ms)
- sampleTime(ms)
- debounceTime(x ms)
- delay(ms)
- delayWhen(innerobs)
- throttleTime(ms)
- timestamp
- Transformación de valores
- defaultIfEmpty()
- endWith
- startWith
- reduce()
- scan()
- pluck
- Útiles
- count()
- every(cond)
- isEmpty()
- tap(x ⇒ function(x))
- Subject
- BehaviorSubject
- ReplaySubject
- AsyncSubject
- Casos de uso
- Evitar llamar varias veces a una misma llamada al servidor
- Cuando solo nos interesa la última petición de llamada recibida
- Encadenar dos peticiones donde la segunda depende de los datos de la primera
- Repetir una llamada Http cada cierto tiempo con actualización de datos sin parpadeo de pantalla
- Combinar datos de un array con otra llamada distinta
- Crear un objeto a partir de distintas llamadas al api
Gestión del estado
- Model Pattern
- Akita
- Implementación de un CRUD con Akita
Creación de una librería para Angular
- Usando @angular/cli después de la versión 6
- Usando @angular/cli antes de la versión 6
- Creación de la librería desde cero
- Uso de packagr para la distribución (Angular -6)
- Configuración externa de la librería
Server rendering
- Introducción
- Pasos para hacer server rendering después de la versión 6
- Pasos para hacer server rendering antes de la versión 6
- Añadimos pre-rendering
Internacionalización
- Haciendo uso del core de Angular
- Indicar los textos que se quieren internacionalizar
- Extracción a fichero de mensajes
- Creación de los ficheros de mensajes por idioma
- Puesta en producción
- Uso de la librería de ngx-translate
- Instalación de las dependencias
- Configuración en el módulo principal
- Estableciendo el idioma por defecto
- Creación de los ficheros de idiomas
- Uso de las traducciones en los componentes
- Uso de las traducciones en los servicios/pipes
Integración y despliegue continuo
- Integración continua con TravisCI y despliegue en Firebase
Ionic
- Como empezar a crear una aplicación (Ubuntu 16.04)
- Conectar con los servicios gratuitos de Ionic PRO
- Establecer monitoring
- Captura automática de los errores
- Captura manual
- Añadir los sourcemaps
- Crear nueva página en el sidemenu
- Navegación
- Eventos de navegación
- Gestión del almacenamiento
- Declaración de múltiples almacenamientos
- Gestión de las variables de entorno
- Creación y carga dinámica de temas
- Implementación de hot deploy
- ¿Qué es el hot deploy?
- Cómo aplicarlo a los proyectos
- Configuración para distintos entornos de ejecución
- Usando Firebase como servidor de producción
- Probando el despliegue en caliente
- Testing unitario y de integración con Jest
- Testing E2E con Cypress
NX: cómo abordar proyectos complejos
- NX al rescate
- Empezando con NX
- Creación de una nueva aplicación
- Creación de una librería como módulo secundario
- Creación de una librería
- Arranque/distribución de la aplicación
- Publicación de una librería
- Cosas a tener en cuenta
- Actualizar el workspace a la última versión de Angular
- Visualizar en un gráfico las dependencias entre aplicaciones y librerías
- Integración de Ionic en un workspace de NX
Principios de diseño y buenas prácticas
- Componentes pequeños y tontos
- No subestimes el poder de los pipes
- Uso de la herencia en los componentes
- No uses funciones para calcular datos dentro de los templates
- Los datos siempre deben fluir en una única dirección
- No dejes a tus componentes jugar con todos los juguetes ni saber nada del estado de la aplicación
- Utiliza servicios proxy para acceder a los datos de un API sin nada más de lógica
- Pasos para abordar una aplicación del mundo real
- Casos de uso
- Layouts
- Bus de notificaciones
- Event Bus genérico
- Mostrar un loading
- Componente genérico para mostrar los errores de validación
- Extracción de la configuración de la aplicación
- Variante haciendo uso de Kubernetes
- Directiva que muestra el elemento mirando permisos
- Visualización dinámica de componentes
- Utilizar la técnica View Model (vm) para centralizar las fuentes de información
- Arquitectura propuesta
- Implementación de un CRUD
DevUI: poniendo orden en el front
- Situación actual en muchas grandes empresas
- ¿Cómo podemos solucionar esto?
- No nos quedemos solo en la teoría
- La automatización es clave
- Conclusiones
NestJS
- Primeros pasos
- Configuración de Visual Studio Code
- Ejecución de los tests
- Arranque de la aplicación
- Configuración del debug en VSCode
- Externalización de la configuración
- Cálculo de la cobertura conjunta (unitarios + integración)
- Creación de un CRUD con API REST
- Utilizando PostgreSQL
- Gestión de errores