Loading spinner gestionado con NgRx

Vamos a crear un componente que nos sirva para gestionar una acción para cargar datos y mostrar un spinner que indique que esta cargando.

El código usado para los ejemplos esta disponible en este repositorio:
https://github.com/theguitxo/marsRoverPhotos

El spinner se puede ver en el despliegue del respositorio, mediante el siguiente enlace:
https://theguitxo.github.io/marsRoverPhotos/

El componente del spinner está formado por el componente, la plantilla y la hoja de estilos.

El componente es sencillo, sólo requiere de dos inputs, uno para obtener la store de NgRx sobre la que se ejecutará la acción y otro para obtener la acción que ejecutará.

import { ChangeDetectionStrategy, Component, Input, OnInit } from "@angular/core";
import { Store } from "@ngrx/store";
import { TypedAction } from "@ngrx/store/src/models";

/**
 * Shows a spinner during a data loading operation
 */
@Component({
  selector: 'app-loader',
  templateUrl: './loader.component.html',
  styleUrls: ['./loader.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class LoaderComponent implements OnInit {
  /**
   * Store that contains the action for load the data
   */
  @Input() store!: Store<any>;
  /**
   * Action for load the data
   */
  @Input() action!: TypedAction<string>;

  /**
   * Angular life cycle init: dispatch the action to load the data
   */
  ngOnInit(): void {
      this.store.dispatch(this.action);
  }
}

La plantilla de HTML sólo contiene los tags necesarios para mostrar el spinner. En el repositorio de ejemplo se usó Angular Material, por lo que usamos <mat-spinner></mat-spinner>

<div class="loader">
  <mat-spinner></mat-spinner>
  <div class="loading-text">Loading...</div>
</div>

La hoja de estilos nos sirver para dar formato a elementos que no forman parte de Angular Material

.loader {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: 3rem 0;

  .loading-text {
    font-size: 2rem;
    padding-top: 2rem;
    color: #3f51b5;
  }
}

Usar el loading spinner en un componente que carga datos.

Para usar el loading spinner en un componente que necesite cargar datos tendremos que preparar los dos valores que se han de pasar como parámetros.

El Input store

Se necesita la store sobre la que se ejecutará al acción. Esta la recibirá el componente que usará el spinner como parámetro en su constructor. En caso que se declaré como un valor público, si la tenemos declarada como un valor privado (el caso del ejemplo), podemos usar un get para poder obtenerlo y usarlo en la plantilla como parametro del spinner

/**
 * Returns a reference to the store
 */
get storeRef(): Store<StoreState> {
  return this.store;
}

/**
 * Constructor for the component
 * @param {Router} router Angular service that provides tools for work with routes
 * @param {Store<StoreState>} store Store for app data
 */
constructor(
  private readonly router: Router,
  private readonly store: Store<StoreState>
){}

El Input action

Este input servirá para indicar al componente que acción de la store a de ejecutar para cargar los datos. Se declara una propiedad de tipo Action y se le asigna el valor.

  /**
   * Action for load de photos list
   */
  loadCamPhotosAction!: Action;

  /**
   * Sets the actions for the component
   */
  private setActions(): void {
    this.loadCamPhotosAction = ROVER_ACTIONS.loadCamPhotos();
  }

Insertar el spinner en la plantilla

El componente se inserta en la plantilla del componente que deba usarlo, teniendo en cuenta que debe incluir una directiva *ngIf para que sólo se muestra, y, en consecuencia, cargue datos, cuando sea necesario

<app-loader
  *ngIf="!(loaded | async) && !(hasDetailsData | async)"
  [store]="storeRef"
  [action]="loadCamPhotosAction">
</app-loader>

Screenshot

Esta web utiliza cookies propias para su correcto funcionamiento. Contiene enlaces a sitios web de terceros con políticas de privacidad ajenas que podrás aceptar o no cuando accedas a ellos. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Ver
Privacidad