Skip to content
forked from ngneat/loadoff

🤯 When it comes to loaders, take a load off your mind...

License

Notifications You must be signed in to change notification settings

ritox842/loadoff

 
 

Repository files navigation


MIT commitizen PRs styled with prettier All Contributors ngneat spectator

When it comes to loaders, take a load off your mind...

Installation

npm install @ngneat/loadoff

Create a Loader

To create a loader, call the loadingFor function and specify the loaders you want to create:

import { loadingFor } from '@ngneat/loadoff';

@Component({
  template: `
    <button>
      Add
      <spinner *ngIf="loader.add.inProgress$ | async"></spinner>
    </button>
    
    <button>
      Edit 
      <spinner *ngIf="loader.edit.inProgress$ | async"></spinner>
    </button>
    
    <button>
      Delete 
      <spinner *ngIf="loader.delete.inProgress$ | async"></spinner>
    </button>
  `
})
class UsersTableComponent {
  loader = loadingFor('add', 'edit', 'delete');

  add() {
    this.service.add().pipe(
      this.loader.add.track()
    ).subscribe();
  }

  edit() {
    this.service.add().pipe(
      this.loader.edit.track()
    ).subscribe();
  }

  delete() {
    this.service.add().pipe(
      this.loader.delete.track()
    ).subscribe();
  }
}

Async State

AsyncState provides a nice abstraction over async observables. You can use the toAsyncState operator to create an AsyncState instance which exposes a loading, error, and res state:

import { AsyncState, toAsyncState } from '@ngneat/loadoff';

@Component({
  template: `
    <ng-container *ngIf="users$ | async; let state">
      <p *ngIf="state.loading">Loading....</p>
      <p *ngIf="state.error">Error</p>
      <p *ngIf="state.res">
        {{ state.res | json }}
      </p>
    </ng-container>
  `
})
class UsersComponent {
  users$: Observable<AsyncState<Users>>;

  ngOnInit() {
    this.users$ = this.http.get<Users>('/users').pipe(
      toAsyncState()
    );
  }

}

You can also use the *subscribe directive instead of *ngIf.

createAsyncState

You can use the createAsyncState to manually create an instance of AsyncState:

import { createAsyncState } from '@ngneat/loadoff';


class UsersComponent {
  state = createAsyncState()
}

The initial state of AsyncState instance is:

{
  error: undefined,
  res: undefined,
  loading: true,
  complete: false,
  success: false,
};

You can always override it by passing a partial object to the createAsyncState function:

import { createAsyncState } from '@ngneat/loadoff';


class UsersComponent {
  state = createAsyncState({ loading: false, complete: true, res: data })
}

createSyncState

Sometimes there could be a more complex situation when you want to return a sync state which means setting the loading to false and complete to true:

import { createSyncState, toAsyncState } from '@ngneat/loadoff';


class UsersComponent {
  ngOnInit() {
    source$.pipe(
      switchMap((condition) => {
        if(condition) {
          return of(createSyncState(data));
        }

        return inner$.pipe(toAsyncState())
      })
    )
  }
}

Helper Functions

import { isSuccess, hasError, isComplete, isLoading } from '@ngneat/loadoff';

class UsersComponent {
  loading$ = combineLatest([asyncState, asyncState]).pipe(someLoading())

  ngOnInit() {
    this.http.get<Users>('/users').pipe(
      toAsyncState()
    ).subscribe(res => {
      if(isSuccess(res)) {}
      if(hasError(res)) {}
      if(isComplete(res)) {}
      if(isLoading(res)) {}
    })
  }

}

Async Storage State

AsyncStore provides the same functionality as AsyncState, with the added ability of being writable:

import { AsyncState, createAsyncStore } from '@ngneat/loadoff';

@Component({
  template: `
    <ng-container *ngIf="store.value$ | async; let state">
      <p *ngIf="state.loading">Loading....</p>
      <p *ngIf="state.error">Error</p>
      <p *ngIf="state.res">
        {{ state.res | json }}
      </p>
    </ng-container>
    
    <button (click)=""updateUsers()">Update Users</button>
  `
})
class UsersComponent {
  store = createAsyncStore<Users>();

  ngOnInit() {
    this.users$ = this.http.get<Users>('/users').pipe(
      this.store.track()
    );
  }
  
  updateUsers() {
    this.store.update((users) => {
      return [];
    });
  }

}

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Netanel Basal

📖 🤔 ⚠️

This project follows the all-contributors specification. Contributions of any kind welcome!

Icons made by Freepik from www.flaticon.com

About

🤯 When it comes to loaders, take a load off your mind...

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 79.0%
  • JavaScript 14.7%
  • HTML 5.7%
  • Other 0.6%