Fundamentos
Comandos
npm i -g @angular/cli
Instala el CLI de Angularng version
Verifica tu instalaciónng new my-project
Crea tu primer proyectong serve -o --port=3500
Lanzar el servidor en un puerto especificong g c components/[name]
Generar componentes, para generar en un modulo específico al final agregarIn Angular 14:
ng g s services/[name]
Generar serviciosng g p [name]
Genera pipesng g d [d]
Genera directivasng g interceptor interceptors/time --flat
Crea interceptorng generate config karma
Agrega la configuración de karma, en la version 15+ de Angular ya no aparece este archivo de configuracionng generate environments
Genera los archivos para los diferentes ambientes v15+ng g m <module-name>
Genera un módulo, puede ser un módulo compartido por ejemplo, con--routing
le indica a Angular que tiene que crear, además del módulo, el archivo base para agregarle rutas a este nuevo módulo.ng g g <guardian-name>
Crea un guardianng update
Actualiza versón de Angular
String Interpolation
Es la manera de enviar datos desde nuestro componente hacia la vista. Utilizando el doble símbolo de llaves {{ }}
. Si son privados no. Usado para renderizar el contenido de los elementos html.
Property Binding
Es la manera que dispone Angular para controlar y modificar las propiedades de los distintos elementos de HTML. Para esto, simplemente utiliza los corchetes [] para poder modificar dinámicamente ese atributo desde el controlador. Recomendado para cuando se usan objetos. Cominicación del componente a la vista y los datos van en una única dirección
Se puede usar en
El atributo src de la etiqueta
<img>
para modificar dinámicamente una imagen.El atributo href de un
<a>
para modificar un enlace. El atributo value de un<input>
para autocompletar un valor de un formulario.El atributo disable de un
<input>
para habilitar/deshabilitar un campo de un formulario.
Event Binding
Permite controlar los eventos que suceden en estos elementos. Para esto utiliza los paréntesis () para el bindeo de la propiedad del elemento. Comunicación de la vista al componente
Puedes enviarle al controlador el evento completo que se produce en la vista. Para esto, solo declara un parámetro $event
en el método que se encuentra escuchando el evento.
ngModel
El atributo ngModel
permite el intercambio de datos de forma bidireccional entre el componente y la vista. Lo que suceda en el componente, se verá reflejado en la vista. Lo que se suceda en la vista, inmediatamente impactará en el componente, es decir ya no necesitamos esto:
Por
Para utilizar ngModel
, es necesario hacer uso e importar FormsModule
y agrégalo en los imports en archivo app.module.ts
, que es el módulo principal de toda aplicación Angular.
Podemos agregar una variable en el template #inputName="ngModel" (inputName es un ejemplo, puede ser otro nombre) para ver sus propiedades o validaciones en el archivo html
If … else
ngFor
ngSwitch
Class binding
La versatilidad de Angular te permite agregar o quitar clases y estilos a tus elementos HTML a partir de condicionantes bindeando la propiedad [class]
Imagina que tienes en tu componente una propiedad llamada isActive que agregará la clase active-color si esta es verdadera o quitará la clase si es falsa. Luego ya puedes darle los estilos que más te gusten al elemento HTML en tu hoja de estilos utilizando la clase active-color.
Style binding
También puedes añadir estilos inline a los elementos HTML bindeando la propiedad [style] seguido de la propiedad CSS que quieres modificar dinámicamente:
NgClass y NgStyle
Puedes bindear la directiva [ngStyle] o [ngClass] y pasarle un objeto con cada propiedad o clase que deseas agregar:
Componentes en Angular
Un componente es una pieza de software con una responsabilidad única y una estructura y funcionalidad determinada, además de ser reutilizable.
Es la parte minima de una página web, consta de un template HTML, archivo de SASS o CSS y archivo de logica (Typescript).
Comunicando componentes
Para enviar información de padre a hijo
Puedes utilizar el decorador @Input()
para marcar una propiedad de una clase como punto de entrada de un dato.
Los decoradores pueden ser usados en clases y propiedades
También puedes cambiar el nombre el Input especificando el nombre de la propiedad que quieras que este utilice al inicializar el componente.
Con el signo de exclamación le decimos a Angular (o Typescript) que esa propiedad sí va a existir. @Input() set
es una alternativa al ngOnChanges
para poder escuchar en particular un cambio de un solo @Input
Lo que va dentro de los parentesis dentro del @Input('<name>')
es para cambiarle el nombre el input cuando se llama desde otro componente. Se usa property binding para acceder a este método.
Comunicación hijo a padre
A partir de la emisión de un evento, el decorador @Output()
permite enviar mensajes desde un componente hijo hacia el padre.
Comunicación desde el componente hijo al padre mediante con ViewChild()
Mediante ViewChild, el padre crea el componente hijo y tiene acceso a sus datos y atributos:
En el hijo:
En el padre:
La particularidad de éste método es que tenemos que esperar a que la vista esté totalmente cargada para acceder a los atributos del hijo. Para ello creamos un método de Angular llamado ngAfterViewInit() en el que simplemente inicializamos la variable con el valor del atributo del hijo (el hijo lo declaramos como @ViewChild(ChildComponent)).
@ViewChild
Es posible que existan situaciones en las que desee acceder a una directiva, componente secundario o elemento DOM de una clase principal de componentes. El decorador ViewChild
devuelve el primer elemento que coincide con una directiva, un componente o un selector de referencia de plantillas concreto.
Differencia entre ng-template, ng-container, and ng-content
1) <ng-template></ng-template>
<ng-template></ng-template>
El elemento <ng-template>
se utiliza en Angular junto con directivas estructurales (como *ngIf
, *ngFor
, [ngSwitch]
y directivas personalizadas). Estos elementos de plantilla no se renderizan por sí mismos, sino que se renderizan condicionalmente en el DOM. Permiten crear plantillas dinámicas que pueden ser personalizadas y configuradas.
En el ejemplo, si la condición es falsa, se mostrará "No se debería mostrar"; de lo contrario, se mostrará el contenido del <ng-template>
como "Se debería mostrar".
2) <ng-container></ng-container>
<ng-container></ng-container>
<ng-container>
es una directiva sencilla que agrupa elementos en una plantilla sin afectar el DOM, estilos o diseño. Es útil cuando no deseas agregar elementos adicionales como <div>
al DOM. (Parecido al React.Fragment)
Este ejemplo muestra cómo usar <ng-container>
para evitar el error de tener múltiples directivas estructurales en un solo elemento, sin agregar elementos adicionales al DOM.
3) <ng-content></ng-content>
<ng-content></ng-content>
Imagina que tienes un componente padre (ParentComponent
) y un componente hijo (ChildComponent
). Quieres que el componente padre pase contenido dinámico al componente hijo para ser mostrado.
Componente Hijo (child.component.html)
Componente Hijo (child.component.ts)
Componente Padre (parent.component.html)
Componente Padre (parent.component.ts)
Resultado
En el navegador, se verá lo siguiente dentro del componente hijo:
El contenido que se encuentra entre las etiquetas <app-child></app-child>
en el componente padre se proyecta en el componente hijo en el lugar donde se encuentra <ng-content></ng-content>
.
Uso de Selectores en <ng-content>
<ng-content>
Puedes utilizar el atributo select
para proyectar contenido específico basado en selectores. Aquí tienes un ejemplo más avanzado:
Componente Hijo con Selectores (child.component.html)
Componente Padre con Selectores (parent.component.html)
Resultado
En el navegador, el contenido se organizará de la siguiente manera dentro del componente hijo:
Este ejemplo muestra cómo puedes proyectar diferentes partes del contenido en ubicaciones específicas dentro de tu componente hijo usando selectores con <ng-content>
.
Referencias
Para más información, puedes consultar la documentación oficial de Angular:
Resumiendo:
ng-content
muestra contenido hijo en una plantilla.ng-container
agrupa elementos sin renderizar nada adicional en el DOM.ng-template
agrupa contenido que no se renderiza directamente, pero puede usarse en otras partes de la plantilla o código.
Decoradores
En Angular, los decoradores son una característica fundamental que permite a los desarrolladores añadir metadatos a las clases, métodos, propiedades y parámetros. Estos metadatos son utilizados por Angular para proporcionar funcionalidad adicional a las aplicaciones. Los decoradores en Angular se basan en la propuesta de decoradores de JavaScript y son funciones que toman un argumento y devuelven otro, generalmente una versión mejorada del original.
Tipos de Decoradores en Angular
@Component: Este decorador se utiliza para definir una clase como un componente de Angular, asociando la clase a una plantilla HTML, estilos y lógica de negocio.
@Directive: Define una clase como una directiva. Las directivas pueden modificar el comportamiento de elementos del DOM.
@Injectable: Marca una clase como disponible para ser inyectada mediante el sistema de inyección de dependencias de Angular. Esto es crucial para los servicios.
@NgModule: Declara una clase como un módulo de Angular. Los módulos organizan un conjunto de componentes, directivas, servicios y otros elementos relacionados.
@Input y @Output: Estos decoradores se utilizan en componentes para definir propiedades que pueden recibir datos de componentes padre (
@Input
) o emitir eventos hacia componentes padre (@Output
).
Beneficios de Usar Decoradores
Claridad y Mantenibilidad: Los decoradores proporcionan una forma clara y concisa de declarar el comportamiento y la configuración de las clases.
Reutilización de Código: Permiten aplicar lógica común a múltiples clases de manera uniforme.
Metadatos: Facilitan la adición de metadatos a las clases, que pueden ser utilizados por Angular y otras bibliotecas para personalizar el comportamiento.
Ciclo de Vida
Constructor
: Se ejecuta una sola vez antes del render, no se deben ejecutar funciones asincronas.ngOnChanges
: Corre antes y durante en el render, siempre que detecte cambios en el@Input
.ngOnInit
: Se ejecuta una sola vez despues del render, aqui se pueden ejecutar funciones asincronas.ngAfterViewInit
: Se ejecuta despues del render y de que el componente y sus componentes hijos se han renderizado.NgOnDestroy
: Se ejecuta cuando se elimina el componente.
Estilos
Cada componente tiene un scope hacia sus propis estilos, lo que significa que un componente padre no pude actualizar los estilos del componente hijo directamente, para lograrlo de ese modo se pueden usar en los estilos globales, ahí si se pueden modificar los estilos utilizando las etiquetas que empiezan con app, ejemplo:
Uso de ng lint
Revisa el código del proyecto para ver si se están cumpliendo las reglas definidas en el archivo tslint.json
Nos permite visualizar el resultado de la revisión con un formato json.
Corrige automáticamente, dentro de lo posible, los errores encontrados.
Servicios
Un servicio es la forma que utiliza Angular para modularizar nuestra aplicación y crear código reutilizable, este tendrá una determinada lógica de negocio que puede ser usada por varios componentes u otros servicios.
Dentro de los servicios Angular tambien puede hacer peticion http, y utiliza observables en lugar de Promesas puras, ademas de poder almacenar y compartir el estado de la aplicacion.
Inyección de dependencias
Imagínate que tienes el siguiente panorama: Un Servicio A que emplea el Servicio B y este a su vez utiliza el Servicio C.
Si tuvieses que instanciar el Servicio A, primero deberías: instanciar el C para poder continuar con el B y luego sí hacerlo con el A. Se vuelve confuso y poco escalable si en algún momento también tienes que instanciar el Servicio D o E.
La inyección de dependencias soluciona las dependencias de una clase por nosotros.
Cuando instanciamos en el constructor el servicio A, Angular por detrás genera automáticamente la instancia del servicio B y C sin que nosotros nos tengamos que preocupar por estos.
Este le proporcionó a la clase el decorador @Injectable({ ... }) con el valor providedIn: 'root' que determina el scope del servicio, o sea, determina que el mismo estará disponible en toda el módulo de tu aplicación por default.
Inyección de Dependencias (Dependency Injection o DI) es un patrón de diseño en el que una clase requiere instancias de una o más clases y en vez de generarlas dentro de su propio constructor, las recibe ya instanciadas por un mecanismo externo.
Singleton
La inyección de dependencias no es el único patrón de diseño que Angular usa con sus servicios. También hace uso del patrón Singleton para crear una instancia única de cada servicio.
Si tienes un servicio que se utiliza en N cantidad de componentes (u otros servicios), todos estarán utilizando la misma instancia del servicio y compartiendo el valor de sus variables y todo su estado.
Nota: EL patrón Singleton se refiere a la creación de una sola instancia de una clase, mientras que Dependency Injection se refiere a la forma en que las dependencias de una clase son administradas y pasadas. Aunque pueden parecer similares y ser utilizados juntos en algunos casos, son conceptos separados con objetivos distintos.
Solo debes tener cuidado con las dependencias circulares. Cuando un servicio importa a otro y este al anterior. Angular no sabrá si vino primero el huevo o la gallina y tendrás un error al momento de compilar tu aplicación.
Pipes
En Angular, los "pipes" son una característica poderosa que permite transformar los datos en las vistas de manera declarativa. Los pipes pueden ser usados para formatear los datos de diversas maneras sin necesidad de modificar el modelo de datos. Son similares a los filtros en otras tecnologías de front-end como AngularJS y permiten realizar operaciones comunes como formatear fechas, números, cadenas de texto, y más.
Características de los Pipes
Declarativos: Se usan directamente en las plantillas (templates) de los componentes.
Reutilizables: Se pueden definir una vez y reutilizar en múltiples componentes y plantillas.
Puros e Impuros: Los pipes puros se recomiendan para transformaciones simples y no mutables, mientras que los impuros se utilizan para transformaciones más complejas y mutables.
Uso de Pipes en Angular
Sintaxis Básica
Los pipes se aplican en las plantillas usando el símbolo de barra vertical (|
). La sintaxis básica es:
Pipes Incorporados en Angular
Angular proporciona varios pipes incorporados que cubren las necesidades comunes:
DatePipe: Formatea fechas.
UpperCasePipe y LowerCasePipe: Convierte el texto a mayúsculas o minúsculas.
CurrencyPipe: Formatea números como moneda.
DecimalPipe: Formatea números decimales.
PercentPipe: Formatea números como porcentaje.
JsonPipe: Convierte un objeto a una cadena JSON.
Ejemplos de Uso
Formatear una Fecha
Esto mostrará currentDate
formateada como una fecha completa, por ejemplo, "Wednesday, June 14, 2023".
Convertir a Mayúsculas
Esto convertirá el valor de name
a mayúsculas.
Formatear un Número como Moneda
Esto mostrará price
formateado como una moneda en dólares estadounidenses.
Creación de Pipes Personalizados
Además de los pipes incorporados, puedes crear tus propios pipes personalizados para casos de uso específicos. Aquí hay un ejemplo de cómo crear y usar un pipe personalizado.
Definir un Pipe Personalizado
Primero, se define el pipe utilizando el decorador @Pipe
y se implementa la interfaz PipeTransform
:
Usar el Pipe Personalizado
Después de definir el pipe, se puede usar en una plantilla de la misma manera que los pipes incorporados:
Esto elevará 2 a la potencia de 10, mostrando 1024
.
Conclusión
Los pipes en Angular son una herramienta poderosa y flexible para transformar y formatear datos directamente en las plantillas. Los pipes incorporados cubren muchas necesidades comunes, y los pipes personalizados permiten extender la funcionalidad de manera específica para la aplicación. Usar pipes mejora la legibilidad y la mantenibilidad del código al separar la lógica de formateo de los datos del propio modelo de datos.
Directivas
Angular utiliza el concepto de directiva para cambiar la apariencia o el comportamiento de un elemento en el HTML. Las directivas se usan para modificar el DOM de forma directa y también se pueden modificar los atributos aunque no es lo recomendable.
Se usa @HostListener('mouseleave')
para escuchar eventos del elemento
Pasando datos a una directiva Finalmente, si tienes la necesidad de que tu directiva reciba algún tipo de valor, lo mejor es apoyarte en el decorador que ya conoces @Input()
.
Estado de la aplicación
Esto se logra implementando un store de datos, es decir, un lugar donde estan los estados que se desean compartir, los store de datos suelen implementarse haciendo uso de Observables. Esto se logracon la libreir rxjs.
Sepuede usar de la siguiente manera
Consumo de API con Angular
Comienza importando el módulo
HttpClientModule
, en el módulo principal de tu aplicación desde @angular/common/http.Crea un servicio para realizar todos los llamados a una API que necesites. En este servicio tienes que importar el cliente HTTP de Angular y crear un método por cada endpoint para el que necesites efectuar una petición.
Importa este nuevo servicio en tus componentes para efectuar los llamados a la API. Todo el cliente HTTP de Angular está basado en Observables, por lo tanto, es recomendable suscribirse al método del servicio para obtener los datos cuando la API responda.
Parámetros y headers
Los endpoints del tipo GET suelen recibir información por parámetros de URL. Por ejemplo:
https://example.com/api/productos?offset=0&limit=10 https://example.com/api/productos?q=XXXXX
Observable vs. Promesa
Observables
Utilizan el patrón de diseño “observador” que centraliza la tarea de informar un cambio de estado de un determinado dato o la finalización de un proceso, notificando a múltiples interesados cuando esto sucede sin necesidad de que tengan que consultar cambios activamente.
Características:
Emiten múltiples datos
Permiten escuchar cualquier tipo de proceso, (peticiones a una API, lectura de archivos, etc.)
Notifican a múltiples interesados
Pueden cancelarse
Manipulan otros datos (transformar, filtrar, etc.) con rxjs.
Son propensos al callback hell
Ejemplo:
Promesas
Las promesas son un método algo más sencillo y directo para manipular procesos asincrónicos en Javascript.
Características:
Tienen dos posibles estados resuelto y rechazado
Ofrecen mayor simplicidad
Emiten un único valor
Evitan el callback hell
No se puede cancelar
Proveen una robusta API nativa de Javascript disponible desde ES 2017
Constituyen librerías populares como AXIOS o Fetch
Observable a Promesa
Promesa a Observable
En los pipes se pueden usar otras funciones de rxjs como filter
, retry(3)
, catchError
, map
, tap
etc.
CORS
Se pueden saltar los CORS con un archivo proxy.config.json
Manejo de errores
En el servicio
En el componente
Solucionar el Infierno de Callbacks
Promise.all([]) en Observables
Interceptors
Aplicando el patrón: Smart and Dumb components
Dumb component
Debe encargarse de la desplegar y visualizar datos e interacción.
Smart component
Trae datos para mandarlos a al dumb component y manejan la logica y flujos de datos.
Los dumb components tienen de apellido .component y los smart components .container
Ambientes de Desarrollo y Producción
En tu proyecto de encontrarás una carpeta llamada environments y por defecto con dos archivos dentro (Los nombres son diferentes dependendo de la versión):
environment.development.ts
environment.ts
Ambos lucen de manera muy similar.
Nota: Con la versión 15+ se necesitan generar manualmente con el comando
En el archivo angular.json
agrega la configuración para cada ambiente
Build
Para mejorar la caché en Angular cambiando el nombre de los archivos generados por ng build
, puedes utilizar la técnica de "output hashing". Esta técnica agrega un hash único a los nombres de los archivos cada vez que se genera una nueva versión de la aplicación. Así, cuando el contenido de un archivo cambia, también lo hace su nombre, obligando al navegador a descargar la nueva versión en lugar de usar la versión en caché.
Pasos para Implementar Output Hashing en Angular
Configura el Output Hashing en el Archivo angular.json:
Debes asegurarte de que el archivo
angular.json
esté configurado para incluir hashing en los nombres de los archivos. Esto se puede hacer en la configuración de construcción de producción.Abre
angular.json
y encuentra la configuración de build dentro deprojects.[your-project-name].architect.build.options
. Añade o asegúrate de que la opciónoutputHashing
esté establecida enall
.Construir la Aplicación con el Comando ng build:
Ejecuta el comando
ng build
con la opción--prod
para asegurarte de que se construya en modo producción y que se apliquen los hashes.Esto generará los archivos de tu aplicación en la carpeta
dist
con nombres que incluyen un hash, por ejemplo,main.abc123.js
.
Verificación de los Archivos Generados
Después de ejecutar el comando de build, revisa la carpeta dist
para asegurarte de que los archivos tienen nombres con hashes:
Conclusión
Usar el "output hashing" en Angular es una técnica efectiva para mejorar la gestión de la caché. Esta práctica asegura que los usuarios siempre obtengan la versión más reciente de los archivos, evitando problemas de caché obsoleta y mejorando la experiencia del usuario.
Last updated