简体   繁体   English

在所有子组件和子子组件中的数据到达Angular中之前,显示加载栏的最佳方法是什么

[英]What is the best way to show loading bar until data in all child and sub child components arrive in Angular

I have components with loading bar, which shows and hides from boolean variable called isLoading . 我有带有加载栏的组件,它显示和隐藏名为isLoading布尔变量。 For example: 例如:

ngOnInit() {
  this.isLoading = true;
  this.someService.getAll().subscribe(data => { 
    // some code...
    this.isLoading = false;
  });
}
<loading-bar *ngIf="isLoading"></loading-bar>

But I have a problem, when there are child components in the main component and the data loads from them. 但是我有一个问题,当主要组件中有子组件并且从中加载数据时。 The loading bar should be in the main component and should be hide only when data from all child components arrive. 加载栏应位于主组件中,并且仅在来自所有子组件的数据到达时才隐藏。 What is the best way to achieve this. 实现此目标的最佳方法是什么。

You can use HttpInterceptor to sense any HTTP activity going on in the application and create a service that keep HTTP activity flag inside it. 您可以使用HttpInterceptor来感知应用程序中正在进行的任何HTTP活动,并创建一个在其中保留HTTP活动标志的服务。 Now in your root component, just check that flag and show a loading spinner. 现在,在您的根组件中,只需检查该标志并显示一个加载微调器即可。 This way you'll not have to individually handle showing of loading bar for each child and sub-child components. 这样,您不必分别处理每个子组件和子组件的加载栏的显示。

The code for HTTPInterceptor and related service shall be like this. HTTPInterceptor和相关服务的代码应与此类似。

 import { Injectable } from '@angular/core'; import { Observable, of, throwError } from 'rxjs'; import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; import { BehaviorSubject } from 'rxjs'; import { catchError, finalize, map } from 'rxjs/operators'; @Injectable() export class HTTPStatus { private requestInFlight$: BehaviorSubject<boolean>; constructor() { this.requestInFlight$ = new BehaviorSubject(false); } setHttpStatus(inFlight: boolean) { this.requestInFlight$.next(inFlight); } getHttpStatus(): Observable<boolean> { return this.requestInFlight$.asObservable(); } } @Injectable() export class HTTPListener implements HttpInterceptor { constructor(private status: HTTPStatus) { } intercept( req: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> { return next.handle(req).pipe( map(event => { this.status.setHttpStatus(true); return event; }),catchError(error => { return Observable.throw(error); }), finalize(() => { this.status.setHttpStatus(false); }) ) } } 

Inject the HTTPStatus service in your root app-component. 在您的根应用程序组件中注入HTTPStatus服务。

  HTTPActivity: boolean; constructor(private httpStatus: HTTPStatus) { this.httpStatus.getHttpStatus().subscribe(status => { this.HTTPActivity = status; }); } 

In the .html part of your component, now you can show / hide loading bar or spinner by checking the HTTPActivity boolean variable. 现在,在组件的.html部分中,您可以通过检查HTTPActivity布尔变量来显示/隐藏加载栏或微调器。

 <div id="preloader" [hidden]=!HTTPActivity> <div id="loader"></div> </div> 

Ofcourse you'll have to register HTTPListener and HTTPStatus service in the providers array of your module. 当然,您必须在模块的providers数组中注册HTTPListener和HTTPStatus服务。

Thanks. 谢谢。

You can make isLoaded flag for each child component. 您可以为每个子组件创建isLoaded标志。 Then, share the flag state via service to ur parent component. 然后,通过服务共享标记状态到您的父组件。 The isLoaded flag of the parent component would be a combo of isLoaded of children 父组件的isLoaded标志将是孩子的isLoaded的组合

Isn't it the case with the loaders that we put on the entire app itself? 我们放在整个应用程序本身上的加载程序不是这种情况吗?

You need to "implement" HttpInterceptor and use the loader in there by attaching both of these with a loader service. 您需要“实现” HttpInterceptor并在其中使用加载器,方法是将这两者与加载器服务一起附加。

Here's a sample implementation of HttpInterceptor. 这是HttpInterceptor的示例实现。

@Injectable()
export class LoaderInterceptor implements HttpInterceptor {
    constructor(public loaderService: LoaderService) { }
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this.loaderService.show();
        return next.handle(req).pipe(
            finalize(() => this.loaderService.hide())
        );
    }
}

You can read more about it here . 您可以在此处了解更多信息。

You can also go for a counter variable in the LoaderInterceptor above as well. 您也可以在上面的LoaderInterceptor使用计数器变量。 This would clearly be a subject the value of which you would emit to LoaderService (after incrementing/decrementing according to call initiated/completed) where the show variable would turn true when the counter is greater than 0 and vice versa. 显然,这是一个主题,您将向LoaderService发出该主题的值(根据调用已启动/完成的调用递增/递减之后),其中,当计数器大于0时, show变量将变为true ,反之亦然。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM