Skip to content

timf-of/loadoff

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


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 loaderFor function and specify the loaders you want to create:

import { loaderFor } 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 = loaderFor('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 {

  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

Contributing

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 78.3%
  • JavaScript 15.2%
  • HTML 5.9%
  • Other 0.6%