Angular 4+ 精细控制 http 调用以显示/隐藏加载器
Angular 4+ Granular control over http call to show / hide loader
我有一项服务进行 http 调用并将数据作为 Observable 返回,我将它分配给组件中的一个变量,如下所示
this.usersResponse$ = this.dataSvc.getUsers(pageNumber);
在 html 我正在做以下事情
<div *ngIf="usersResponse$ | async as userResponse; else loading">
<ng-container>
<ul>
<li *ngFor="let user of userResponse.data" (click)="detail(user.id)">
<img [src]="user.avatar" alt="">
<p>{{ user.first_name }} {{ user.last_name }}</p>
</li>
</ul>
</ng-container>
</div>
<ng-template #loading>
<app-loading></app-loading>
</ng-template>
我想要实现的是如何在 http 调用之前获得精细控制以显示加载器,然后让 http 调用取回数据并关闭加载器,这样 UI 就会跳动。
感谢您的帮助。
使用完整事件:
this.showLoader=true;
this.usersResponse$ = this.dataSvc.getUsers(pageNumber);
this.usersResponse$.subscribe(null, null, () =>
this.showLoader=false);
在模板中
<app-loading *ngIf="showLoader"></app-loading>
你可以在简单的 monad 的帮助下让它成为反应式的:
https://www.npmjs.com/package/ng-loadable-content
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<UserResponse>>(LoadableContent.initial());
readonly state$ = this._state.asObservable();
constructor(private readonly dataSvc: RemoteService) {
}
reload(pageNumber: number) {
this._state.next(LoadableContent.loading());
this.dataSvc.getUsers(pageNumber)
.subscribe(
res => this._state.next(LoadableContent.loaded(res)),
e => this._state.next(LoadableContent.error(e))
);
}
}
控制器:
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<UserResponse>>;
constructor(private readonly objectStore: ObjectStore) {
this.state$ = objectStore.state$;
this.objectStore.reload(1);
}
}
模板:
<div>
<ng-container *ngIf="state$ | async as state">
<div *ngIf="state | loaded as dto">
<ul>
<li *ngFor="let user of dto.data" (click)="detail(user.id)">
<img [src]="user.avatar" alt="">
<p>{{ user.first_name }} {{ user.last_name }}</p>
</li>
</ul>
</div>
<app-loading *ngIf="state | loading"></app-loading>
<div *ngIf="state | loadError">
Failed to load
</div>
</ng-container>
</div>
我有一项服务进行 http 调用并将数据作为 Observable 返回,我将它分配给组件中的一个变量,如下所示
this.usersResponse$ = this.dataSvc.getUsers(pageNumber);
在 html 我正在做以下事情
<div *ngIf="usersResponse$ | async as userResponse; else loading">
<ng-container>
<ul>
<li *ngFor="let user of userResponse.data" (click)="detail(user.id)">
<img [src]="user.avatar" alt="">
<p>{{ user.first_name }} {{ user.last_name }}</p>
</li>
</ul>
</ng-container>
</div>
<ng-template #loading>
<app-loading></app-loading>
</ng-template>
我想要实现的是如何在 http 调用之前获得精细控制以显示加载器,然后让 http 调用取回数据并关闭加载器,这样 UI 就会跳动。
感谢您的帮助。
使用完整事件:
this.showLoader=true;
this.usersResponse$ = this.dataSvc.getUsers(pageNumber);
this.usersResponse$.subscribe(null, null, () =>
this.showLoader=false);
在模板中
<app-loading *ngIf="showLoader"></app-loading>
你可以在简单的 monad 的帮助下让它成为反应式的:
https://www.npmjs.com/package/ng-loadable-content
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<UserResponse>>(LoadableContent.initial());
readonly state$ = this._state.asObservable();
constructor(private readonly dataSvc: RemoteService) {
}
reload(pageNumber: number) {
this._state.next(LoadableContent.loading());
this.dataSvc.getUsers(pageNumber)
.subscribe(
res => this._state.next(LoadableContent.loaded(res)),
e => this._state.next(LoadableContent.error(e))
);
}
}
控制器:
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<UserResponse>>;
constructor(private readonly objectStore: ObjectStore) {
this.state$ = objectStore.state$;
this.objectStore.reload(1);
}
}
模板:
<div>
<ng-container *ngIf="state$ | async as state">
<div *ngIf="state | loaded as dto">
<ul>
<li *ngFor="let user of dto.data" (click)="detail(user.id)">
<img [src]="user.avatar" alt="">
<p>{{ user.first_name }} {{ user.last_name }}</p>
</li>
</ul>
</div>
<app-loading *ngIf="state | loading"></app-loading>
<div *ngIf="state | loadError">
Failed to load
</div>
</ng-container>
</div>