Reutilización . Una palabra que me ha pasado por la cabeza varias veces recientemente, mientras trabajaba en un proyecto Angular. He decidido crear mis propios reutilizables angulares y un blog sobre la experiencia.

Entonces, ¿qué es exactamente un indicador de carga? Por lo general, es una ruleta de algún tipo con una superposición que evita las interacciones del usuario. No se puede hacer clic en la interfaz de usuario y el enfoque está atrapado. Por lo tanto, el usuario no puede modificar los datos o el estado de la aplicación accidentalmente al interactuar con las entradas detrás de la superposición.
Una vez que se detiene la carga, la superposición con la ruleta se elimina del DOM y el elemento previamente enfocado se enfoca nuevamente.
Empecé con la lógica que activaría la ruleta. Para eso utilicé un BehaviorSubject simple y dos funciones de decorador:
import {BehaviorSubject} from 'rxjs'; import {distinctUntilChanged} from 'rxjs/operators'; const indicatorSubject = new BehaviorSubject(false); export const isLoading$ = indicatorSubject.asObservable().pipe(distinctUntilChanged()); export function startLoadingIndicator(target: any, propertyKey: string | symbol, propertyDescriptor: PropertyDescriptor): any { const original = propertyDescriptor.value; propertyDescriptor.value = (...args) => { indicatorSubject.next(true); const result = original.call(target, ...args); return result; }; return propertyDescriptor; } export function stopLoadingIndicator(target: any, propertyKey: string, propertyDescriptor: PropertyDescriptor): any { const original = propertyDescriptor.value; propertyDescriptor.value = (...args) => { indicatorSubject.next(false); const result = original.call(target, ...args); return result; }; return propertyDescriptor; }
De esta manera, no necesitamos un servicio inyectable para activar o detener la ruleta. Los dos métodos decoradores simples simplemente llaman a .next () en nuestro BehaviorSubject. La variable isLoading $ se exporta como un observable.
Usémoslo en nuestro componente indicador de carga.
get isLoading$(): Observable { return isLoading$; }
Ahora, dentro de su plantilla, puede usar su getter isLoading $ con la tubería asíncrona para mostrar / ocultar toda la superposición.
Como puede ver, extraje la ruleta en su propio componente y he hecho varias otras cosas. Agregué algo de lógica para la captura de enfoque y la capacidad de configurar el tamaño y el color de la ruleta usando un InjectionToken.
import {LoadingIndicatorConfig} from './interfaces/loading-indicator.interfaces'; import {InjectionToken} from '@angular/core'; export const DEFAULT_CONFIG: LoadingIndicatorConfig = { size: 160, color: '#7B1FA2' }; export const LOADING_INDICATOR_CONFIG: InjectionToken = new InjectionToken('btp-li-conf');
Proporcionar objetos de configuración mediante InjectionToken es una buena forma de proporcionar propiedades configurables en el constructor.
constructor(@Inject(LOADING_INDICATOR_CONFIG) private config: LoadingIndicatorConfig) { }
Ahora tenemos que agrupar todo en un NgModule:
import {ModuleWithProviders, NgModule} from '@angular/core'; import {LoadingIndicatorComponent} from './loading-indicator/loading-indicator.component'; import {CommonModule} from '@angular/common'; import {SpinnerComponent} from './spinner/spinner.component'; import {DEFAULT_CONFIG, LOADING_INDICATOR_CONFIG} from './loading-indicator.config'; @NgModule({ declarations: [LoadingIndicatorComponent, SpinnerComponent], imports: [ CommonModule ], exports: [LoadingIndicatorComponent] }) export class LoadingIndicatorModule { static forRoot(): ModuleWithProviders { return { ngModule: LoadingIndicatorModule, providers: [{provide: LOADING_INDICATOR_CONFIG, useValue: DEFAULT_CONFIG}] }; } }
Después de construir la biblioteca e instalarla en una aplicación Angular, activar la ruleta se vuelve extremadamente fácil usando los dos métodos decoradores.
Primero, necesitamos agregar el componente al lugar apropiado en el DOM. Normalmente lo coloco en el componente de entrada de la aplicación, en la parte inferior de la plantilla.
Loading indicator
START LOADING
Como puede ver, el método triggerLoadingIndicator se llama cuando se hace clic en el botón. Ese método es un método decorado:
@startLoadingIndicator triggerLoadingIndicator() { setTimeout(this.triggerLoadingIndicatorStop.bind(this), 500); } @stopLoadingIndicator triggerLoadingIndicatorStop() { console.log('stopped'); }
Y eso es todo. Por supuesto, en una aplicación real, se podría usar para decorar solicitudes y sus respectivos manejadores de respuesta. Un consejo rápido: decore también sus controladores de errores. :)
Muchas gracias por leer esta publicación de blog. Si desea probar la biblioteca mencionada anteriormente, puede encontrar el paquete y las instrucciones para instalarla aquí.
También puedes seguirme en Twitter o GitHub.