web-dev-qa-db-ja.com

Angular 2で遅延読み込みモジュールの読み込み中にアクティビティインジケータを表示する

私のシナリオは次のとおりです。複数のオプションがあるメニューがあります。各メニューはユーザー権限に応じて表示され(既に解決済み)、ほとんどのメニュー項目はモジュールとしてカプセル化され、ほとんどのモジュールは遅延ロードされるため、ユーザーが初めてメニュー項目をクリックするとロードされます(ここまですべて)うまくいきます)、私の要件は、より良いユーザーエクスペリエンスを提供するために、遅延ロードされたモジュールがロードされている間にユーザーがメニューアイテムをクリックした後にアクティビティインジケーターを表示する必要があることです。

これまで、Angular Routerから運が良かったので、canActive、canLoad、canActivateChildインターフェイスを使用してみました。

何か案は?

27
vicmac

次の2つのルーターイベントをリッスンできます。

  • RouteConfigLoadStart
  • RouteConfigLoadEnd

遅延ロードされたモジュールがロードされると起動します。 NavigationStartなどの標準のルーターイベントよりもこれらを使用する利点は、すべてのルート変更で発生しないことです。

ルートAppComponentでそれらを聞いて、スピナーを表示/非表示にします。

app.component.ts

import { Router, RouteConfigLoadStart, RouteConfigLoadEnd } from '@angular/router';

...

export class AppComponent implements OnInit {

    loadingRouteConfig: boolean;

    constructor (private router: Router) {}

    ngOnInit () {
        this.router.events.subscribe(event => {
            if (event instanceof RouteConfigLoadStart) {
                this.loadingRouteConfig = true;
            } else if (event instanceof RouteConfigLoadEnd) {
                this.loadingRouteConfig = false;
            }
        });
    }
}

app.component.html

ここでは単純な文字列ですが、スピナーコンポーネントを使用できます。

<router-outlet></router-outlet>

<ng-container *ngIf="loadingRouteConfig">Loading route config...</ng-container>

Angular v4.2.3でこのアプローチを使用しています

57
Daniel Crisp

このようにできます

  1. app.component.html内
<div class="main-loader" *ngIf="loading">
  <div class="cssload-container" >
      <div class="cssload-whirlpool"></div>
  </div>
</div>
  1. app.component.ts内

    import { Router, NavigationStart, NavigationEnd } from '@angular/router';
    
    
    loading:boolean = false;
    constructor(private router:Router) { 
      router.events.subscribe(event => {
        if(event instanceof NavigationStart) {
          this.loading = true;
          console.log("event started")
        }else if(event instanceof NavigationEnd) {
          this.loading = false;
          console.log("event end")
        }
        // NavigationEnd
        // NavigationCancel
        // NavigationError
        // RoutesRecognized
      });
    
    }
    
  2. cSSで読み込みアニメーション

これがあなたの役に立つことを願っています。ありがとう

24

最初のロード中に、他の遅延ロードされたルートへのリンクをクリックすることができます。そのため、ロードされているルートをカウントする必要があります。

app.component.ts

`` `

export class AppComponent { 

  currentlyLoadingCount = this._router.events.scan((c, e) => this._countLoads(c, e), 0);

  constructor(private _router: Router) { }

  private _countLoads(counter: number, event: any): number {
    if (event instanceof RouteConfigLoadStart) return counter + 1;
    if (event instanceof RouteConfigLoadEnd) return counter - 1;
    return counter;
  }

`` `

app.component.html<ng-container *ngIf="currentlyLoadingCount | async">Loading route config...</ng-container>

1
Azargoth

CSSを使用できます!

<routler-outlet></routler-outlet>
<div class='.loader>
  Just, wait a sec ! I'm loading
</div>

テンプレートで

router-outlet + .loader {
  opacity : 1;
}

.loader {
  opacity : 0;
}

次に、 HTML/CSSの派手なスピナー を作成できます

0
YounesM

iE11との互換性(および対処)を必要とする人のために、受け入れられた答えは機能していません。あるモジュールから別のモジュールに切り替えるときにIE11がローダーをレンダリングしないため、(非常にエレガントではありませんが動作します)回避策を行いました:

MenuItemスイッチのクリックイベントで:

  public navigate(url: string) {
    this.configurationService.loading = true; //service variable linked with html loader

    //let's give time to tortoise IE11 to render loader before navigation...
    let obj = this;
    setTimeout(function() 
    {
      obj.router.navigateByUrl(url);
    }, 1);
  }
0
LeonardoX