When it comes to loaders, take a load off your mind...
npm install @ngneat/loadoff
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();
}
}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.
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 })
}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())
})
)
}
}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)) {}
})
}
}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 [];
});
}
}Thanks goes to these wonderful people (emoji key):
Netanel Basal 📖 🤔 |
This project follows the all-contributors specification. Contributions of any kind welcome!