@sigmaproit/loading-states

Use RxJS to handle Angular Loading States with ease

Usage no npm install needed!

<script type="module">
  import sigmaproitLoadingStates from 'https://cdn.skypack.dev/@sigmaproit/loading-states';
</script>

README

LoadingStates

Use RxJS to handle Angular Loading States with ease

version @angular/core license

import { LoadingStatesBSubject, startLoading, updateLoading } from '@sigmaproit/loading-states';


export class HelloComponent {
  
    dataLoadingStates$ = new LoadingStatesBSub(); // initial value => {loadingState: 'initial', error: null}
    
    getFavouriteCharacters() {
        startLoadingSync(this.dataLoadingStates$); // emits value => {loadingState: 'loading', error: null}
        return this.apiService.getFavouriteCharacters().pipe(
            // emits value => {loadingState: 'done', error: null} in case of succeded request and value
            // emits value => {loadingState: 'empty', error: null} in case of succeded request and emptyChecker is true
            // emits value => {loadingState: 'error', error: returnedError} in case of error and will swallow the error
            updateLoading(this.dataLoadingStates$, {
                swallowError: true,
                emptyChecker: (response) => !response.characters.length
            }),
        );
    }
}

Table Of Contents

Usage

install using npm

npm i --save @sigmaproit/loading-states

add to your component when you need to track the loading states for some request

import { LoadingStatesBSubject, startLoading, updateLoading } from '@sigmaproit/loading-states';


export class HelloComponent {
  
    dataLoadingStates$ = new LoadingStatesBSub(); // initial value => {loadingState: 'initial', error: null}
    
    getFavouriteCharacters() {
        startLoadingSync(this.dataLoadingStates$); // emits value => {loadingState: 'loading', error: null}
        return this.apiService.getFavouriteCharacters().pipe(
            // emits value => {loadingState: 'done', error: null} in case of succeded request and value
            // emits value => {loadingState: 'empty', error: null} in case of succeded request and emptyChecker is true
            // emits value => {loadingState: 'error', error: returnedError} in case of error and will swallow the error
            updateLoading(this.dataLoadingStates$, 
                // the following is optional options
                {
                    swallowError: true,
                    emptyChecker: (response) => !response.characters.length
                }
            ),
            take(1),
        ).subscribe(charactersData => this.charactersData = charactersData);
    }
}

then you can use it in your template

<ng-container *ngIf="dataLoadingStates$ | async as states">

    <div *ngIf="states.loadingState === 'loading'">loading...</div>

    <div *ngIf="states.loadingState === 'error'">
        <div>something went wrong</div>
        <div>Reason : {{states.error.message}}</div>
        <button (click)="getFavouriteCharacters()">Reload</button>
    </div>

    <div *ngIf="states.loadingState === 'empty'">
        There is no Favourite Characters to show! 🤷
    </div>

    <ng-container *ngIf="states.loadingState === 'done'">
        <div *ngFor="let character of charactersData.characters">
            {{character.name}}
        </div>
    </ng-container>

</ng-container>

Helper Pipes

instead of using check the state using its string ID like *ngIf="states.loadingState === 'loading'", you can use helper pipes for each state like isLoading, isError, isEmpty and so on.

So instead of *ngIf="states.loadingState === 'loading'" you can use *ngIf="states.loadingState | isLoading".

To use these pipes, you will have to import LoadingStatesModule in your AppModule or SharedModule if you have one.

import { LoadingStatesModule } from '@sigmaproit/loading-states';

@NgModule({
  imports: [
    BrowserModule,
    // here is the LoadingStatesModule
    LoadingStatesModule,
  ],
})
export class AppModule { }