Logo de Angular

Angular

Comandos


Documentación


Pruebas


Buenas practicas

Usar trackBy en el *ngFor

Me permite renderizar solo los elementos nuevos o que hayan cambiado, y no todos los elementos.
En el archihvo HTML:

<div *ngFor="let item of items; trackBy: trackByFn">
  {{item.id}} - {{item.name}}
</div>

en el archivo TS:

trackByFn(index: number, item: any) {
	return index; // or item.id for objects
}

En la funcion debo devolver un identificador unico para que pueda reconocer el nuevo elemento o el que cambió.

Desuscribirse de los observables

Siempre que usemos el metodo subscribe deberiamos usar el metodo unsubscribe, normalmente en el ngOnDestroy(), ej:

  data$: Observable<any> = this.usersService.getData();
  dataSubscription: Subscription | undefined;
  ngOnInit(): void {
    this.dataSubscription = this.data$.subscribe((data) => {
      console.log(data);
    });
  }
  ngOnDestroy(): void {
    this.dataSubscription?.unsubscribe();
  }

Otra forma seria usando el takeUntil, seria la manera recomendada ya que nos permite desuscribirnos de varios observables cuando se destruye el componente, ej:

  data$: Observable<any> = this.usersService.getData();
  users$: Observable<any> = this.usersService.getUsers();
  unsubscribe$ = new Subject<void>();
  ngOnInit(): void {
    this.data$.pipe(takeUntil(this.unsubscribe$)).subscribe((data) => {
      console.log(data);
    });
    this.users$.pipe(takeUntil(this.unsubscribe$)).subscribe((users) => {
      console.log(users);
    });
  }
  ngOnDestroy(): void {
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }

Podria crear una clase para manejar las desuscripciones.
Ver aquí

Usar el pipe async

Usar el pipe async porq permite suscribirse a un observable o promesa y retorna el ultimo valor que ha emitido, usa el valor del resultado en el template, ademas, permite desuscribirse automaticamente del observable cuando se destruye el componente.
La desventaja es que es un poco mas complejo hacer los tests. Ej:
En el template:

<div *ngFor="let user of users$ | async">
  <div>Name: {{ user.name }}</div>
  <div>Username: {{ user.username }}</div>
</div>

En el archivo TS:

users$: Observable<string[]>;
constructor( private usersService: UsersService ) {
	this.users$ = this.usersService.getUsers();
}

otro ejemplo:

<ng-container *ngIf="user$ | async as user; else loading">
  {{ user.name }} {{ user.lastName }}
</ng-container>
<ng-template #loading> Loading... </ng-template>

Conocer el ciclo de deteccion de cambios de Angular

Para algunos componentes podria usar onPush, en vez del default.
Para cambiarlo voy al componente y en el decorador @Component(), agrego la propiedad:
changeDetection: ChangeDetectionStrategy.OnPush

Usar ngSrc en las imágenes

Cambiar el src de las imágenes por el ngSrc desde Angular 15 para optimización de imágenes y lazy load por defecto.
Recomendado poner el ancho y el alto para que deje el espacio para la imagen y no dé saltos la página.

<img [ngSrc]="product.image" width="640" height="480" />

Usar los archivos environment

Para declarar las variables en ambiente de desarrollo y de produccion, Angular hara el cambio por mi cuando se haga el build de produccion.

Para la optimizacion de angular puedo hacer:

Usar el cdk de angular para distintas funcionalidades o componentes.


Errores


Utilidades


Angular 17:

Angular 16:

Angular material:

libreria de componentes, ya estan estilizados y funcionales.
En la página se ve la documentacion, para su uso:
ng add @angular/material

Ver en el package.json en “dependencies” que este “@angular/material”.
Se trabaja a traves de la importacion de modulos, por ej:
import { MatSliderModule } from '@angular/material/slider';
Se declara en los imports y si se requiere en los exports.

CDK (Component Dev Kit): es un conjunto de funcionalidades para construir componentes UI.

Angularflex: trabajar con el flex de Angular, ejecuto:
npm i -s @angular/flex-layout @angular/cdk

Primeng:

libreria de componentes, ya estan estilizados y funcionales. En la pagina se ve la documentacion, para su uso.
Para instalarlo en nuestro proyecto:
npm install primeng --save
npm install primeicons --save
Revisar en el package.json dentro de “dependencies” que estan “primeicons” y “primeng”.
Dentro del angular.json en “styles” pongo las siguientes lineas:

"node_modules/primeicons/primeicons.css",
"node_modules/primeng/resources/themes/saga-blue/theme.css",
"node_modules/primeng/resources/primeng.min.css"

El tema puede cambiar dependiendo del que yo quiera usar.
Se importa el componente que se quiere utilizar en un modulo, ej:
import { ButtonModule } from 'primeng/button'
y se usa segun la documentacion, ej:
<button pButton type="button" label="Click" ></button> Para usar los colores o variables que usa el tema de primeNg en mi CSS, voy a la ruta:
"node_modules/primeng/resources/themes/saga-blue/theme.css"

Si quiero usar el flex de primeNg que me permite tener clases disponibles en el HTML para usar como flexbox, entonces ejecuto:
npm install primeflex --save
Revisar en el package.json dentro de “dependencies” que esta “primeflex”.
Dentro del angular.json en “styles” pongo la siguiente linea:
"node_modules/primeflex/primeflex.css"

Rxjs:

libreria de Javascript para crear programas asincronos y basados en eventos usando secuencias de observables, proporciona operadores para el manejo de los observables. Nos permite implementar programacion reactiva en Angular. La programacion reactiva esta orientada al manejo de datos asincronos y la propagacion de los cambios. Se trabaja a traves de eventos y suscribirse a ellos, para escuchar cuando se emitan los datos y ejecutar algo.
Los operadores RxJS nos permiten transformar los datos que se emiten y
trabajan sobre el flujo de datos, no con el valor final emitido.

Operadores rxjs

Se deben utilizar bajo el operador pipe. Se trabajan sobre el observable.

Eslint y prettier:

agregar linter y formateador a Angular.
(ver youtube, lista reproduccion angular),
(ver https://github.com/jimyhdolores/config-eslint-prettier-husky-angular)

Mapbox:

API para el uso de mapas.
Pagina y documentacion: mapbox.com
(ver carpeta 09-mapasApp)

ng2charts:

Libreria para usar graficas en Angular.
Pagina y documentacion: valor-software.com/ng2-charts
(ver carpeta 10-graficasApp)

ngx-charts:

Libreria para usar graficas en Angular.
Pagina y documentacion: swimlane.gitbook.io/ngx-charts/
Github: github.com/swimlane/ngx-charts


Victor

Directivas:

Es una funcionalidad disponible para las vistas o archivos html, se debe importar el CommonModule de @angular/common

Formularios:

<form #formContact="ngForm" (ngSubmit)="onSubmit()">
  <input
    type="text"
    name="nombre"
    #nombre="ngModel"
    [(ngModel)]="usuario.nombre"
    required
  />
  <span [hidden]="nombre.valid || nombre.pristine"
    >Este campo es requerido</span
  >
  <input
    type="text"
    name="apellido "
    #apellido="ngModel"
    [(ngModel)]="usuario.apellido"
    required
  />
  <span [hidden]="apellido.valid || apellido.pristine"
    >Este campo es requerido</span
  >
  <input type="submit" value="Enviar" [disabled]="formContact.form.invalid" />
</form>

La funcion onSubmit estaria en el archivo .component.ts cargar FormsModule de @angular/forms

@Input:

recibir datos desde el componente padre en el componente hijo, se debe importar donde se va a utilizar
desde la vista del componente padre:
(app-header seria el componte hijo, pasa un string)
<app-header [nombreEnHijo]="'Juan Pablo'"></app-header>
(pasa una propiedad del componente padre que esta en la logica)
<app-header [nombreEnHijo]="nombreEnPadre"></app-header>
Desde la logica del componente hijo:
@Input() nombreEnHijo: string = ''
Si lo quiero recibir con un nombre distinto debo poner:
@Input('nombreEnHijo') otroNombre: string = ''

@Output:

Pasar datos desde el componente hijo al componente padre, se debe importar donde se va a utilizar.
desde la vista del componente hijo:
<button (click)="seleccionar(nombre)"></button>
desde la logica del componente hijo:
(emito el evento cuando se pulsa el boton y se envia al padre)

@Output() eventoEnHijo = new EventEmitter()
seleccionar(nombre){
	this.eventoEnHijo.emit({nombre})
}

desde la vista del componente padre:
(app-header seria el componte hijo, escucha el evento en el componente hijo eventoEnHijo y lanza el metodo en el componente padre metodoEnPadre)
<app-header (eventoEnHijo)="metodoEnPadre($event)"></app-header>
desde la logica del componente padre:

nombre: string;
metodoEnPadre(event){
	this.nombre = event.nombre
}

Backend mean fernando

Nodemon:

lanzar el servidor de node en modo de desarrollo
(ver documentacion en la pagina)
npm install -g nodemon => para instalar de manera global
npm install --save-dev nodemon => para instalar como dependencia de desarrollo
nodemon index.js => estando en la carpeta del proyecto para lanzar el servidor

puedo poner el siguiente script dentro del package.json "dev": "nodemon index.js" para lanzar el servidor en modo desarrollo
npm run dev => para ejecutar el script

puedo poner el siguiente script dentro del package.json "start": "node index.js" para lanzar el servidor en modo produccion. Este script es el que ejecutaria el hosting para saber su punto de partida
npm start => para ejecutar el script