ng-loadable-content
TypeScript icon, indicating that this package has built-in type declarations

2.0.6 • Public • Published

ng-loadable-content

LoadableContent monad and angular pipes for using it.

Install

npm i ng-loadable-content

Usage

Let's assume we have some api endpoint, which returns an object. We have a service, which returns this object:

import {Observable} from 'rxjs/internal/Observable';

export interface Dto {
    id: number;
    name: string;
}

export interface RemoteService {
    
    loadObject(): Observable<Dto>;
    
}

First we import the module:

import {LoadableContentModule} from 'ng-loadable-content';

@NgModule({
    ...
    imports: [
        ...
        LoadableContentModule
    ]
})
export class AppModule {
}

We want the loader to be shown while we load that object. Usual use-case for this is to have a store:

import {Injectable} from '@angular/core';
import {BehaviorSubject} from 'rxjs';
import {LoadableContent} from 'ng-loadable-content';

@Injectable()
export class ObjectStore {

    private readonly _state = new BehaviorSubject<LoadableContent<Dto>>(LoadableContent.initial());
    readonly state$ = this._state.asObservable();

    constructor(private readonly remoteService: RemoteService) {
    }

    reload() {
        this._state.next(LoadableContent.loading());
        this.remoteService.loadObject()
            .subscribe(
                res => this._state.next(LoadableContent.loaded(res)),
                e => this._state.next(LoadableContent.error(e))
            );
    }

}

We use LoadableContent object to wrap the actual result. This object anytime can answer if the result is already loaded, is it being loading right now or was there any error while we tried to load it.

Next, we use this in a component:

import {Observable} from 'rxjs';
import {LoadableContent} from 'ng-loadable-content';

@Component({
    selector: 'app-object',
    templateUrl: './object.component.html',
    providers: [ObjectStore]

})
export class ObjectComponent {

    readonly state$: Observable<LoadableContent<Dto>>;

    constructor(private readonly objectStore: ObjectStore) {
        this.state$ = objectStore.state$;
        this.objectStore.reload();
    }

}

and the template.

<div>
    
    <ng-container *ngIf="state$ | async as state">
        <div *ngIf="state | loaded as dto">{{dto.name}}</div>
        <mat-progress-bar *ngIf="state | loading" mode="indeterminate"></mat-progress-bar>
        <div *ngIf="state | loadError">
            Failed to load dto
        </div>
    </ng-container>

</div>

We can use special pipes loading, loaded and loadError to select the required state.

We can also transform the result with map() method like this:

import {Observable} from 'rxjs';
import {LoadableContent} from 'ng-loadable-content';
import {map} from 'rxjs/internal/operators';

export class ObjectComponent {

    readonly state$: Observable<LoadableContent<string>>;

    constructor(private readonly objectStore: ObjectStore) {
        this.state$ = objectStore.state$.pipe(
            map(s => s.map(_ => _.name))
        );
        this.objectStore.reload();
    }

}

The loadable content can be transformed to loading and error state preserving its value. This can be useful when you want to show the loader above the content (e.g. table), but do not want the content to disappear.

import {Injectable} from '@angular/core';
import {BehaviorSubject} from 'rxjs';
import {LoadableContent} from 'ng-loadable-content';

@Injectable()
export class ObjectStore {

    private readonly _state = new BehaviorSubject<LoadableContent<Dto>>(LoadableContent.initial());
    readonly state$ = this._state.asObservable();

    constructor(private readonly remoteService: RemoteService) {
    }

    reload() {
        const current = this._state.value;
        this._state.next(current.toLoadingState);
        this.remoteService.loadObject()
            .subscribe(
                res => this._state.next(LoadableContent.loaded(res)),
                e => this._state.next(current.toErrorState(e))
            );
    }

}

Package Sidebar

Install

npm i ng-loadable-content

Weekly Downloads

7

Version

2.0.6

License

ISC

Unpacked Size

35.6 kB

Total Files

19

Last publish

Collaborators

  • penkov