2017-10-04 2 views
0

MyComponentはサービスを使用してデータを取得し、そのデータをレンダリングします。ただし、ユーザーがログインするまで、サービスはデータを取得できません。ユーザーが最初に '/ myPage'ルートに移動すると、コンテナコンポーネントにログインコンポーネントが表示されます。しかし、ログインコンポーネントが(MyComponentと評価される)ng-contentの代わりにレンダリングされても、MyComponentはangleで初期化され、フェッチし、ログインする前にサービスが早すぎてデータをフェッチする原因となります。したがって、ユーザーが正常にログインし、MyComponent最後にレンダリングすると、初期データサービスで何も返されなかったデータはありません。角度コンポーネントがレンダリングされるときに関数を実行する方法は?

コンポーネントをレンダリングするまでデータの取得を延期するにはどうすればよいですか? MyComponent内のさまざまなライフサイクルメソッドをすべて成功させようと試みました。

app.component

<container> 
    <router-outlet></router-outlet> 
</container> 

コンテナコンポーネント

<div *ngIf="!userService.getLoggedInUser()"> 
    <login></login> 
</div> 

<div *ngIf="userService.getLoggedInUser()"> 
    <ng-content></ng-content> 
</div> 

ルーティングモジュール

const routes: Routes = [ 
    { path: 'myPage', component: myComponent } 
]; 

私のコンポーネント

export class MyComponent { 
    data 

    constructor(private dataService: DataService) {} 

    ngOnInit() { 
     //how can i make run this service AFTER the component renders? i know 
     //ngOnInit is definitely not the correct lifecycle method, but what is? 
     this.dataService.get().then((data) => this.data = data); 

    } 
    } 
+0

あなたが探しているのは:https://angular.io/api/core/AfterViewInitです。 OnInitと同じ方法で使用します(インポート、実装、ngAfterViewInit(){...}) –

+0

私はあなたが間違った方法で行くと思います。あなたのケースでは、どこにでもチェックユーザーのためにあなたの条件を追加する必要があるので、ログに記録されます。つまり、コンポーネントがロードされ、すべてのjsファイルを検索して確認できるということです。そしておそらく誰かがxss攻撃をすることができます。角度をつけて、我々はガードを構築するより良い方法を持っています。そこに良い例があります:http://jasonwatmore.com/post/2016/09/29/angular-2-user-registration-and-login-example-tutorial –

+0

@RomaSkydanの情報に感謝します。しかし、私はセキュリティの問題が何であるか正確には分かりません。はい、クライアントはログインしているユーザーを確認しますが、サーバー側にトークンがあるセキュリティチェックもあります(これがユーザーがログインした後にデータを取得する必要がある理由です)。セキュリティ上の問題がどこにあるのか正確に説明できますか? – Simon

答えて

2

ngOnInitは、コンポーネントのデータを取得するために使用される通常の方法です。だから、何かがうまくいかないのであれば、どこかに問題があると私は推測しています。

ルートガード

例えば、ログインダイアログを提示する一つの一般的な方法ではなくngIfのルートガードを使用することです。つまり、このようになります:

import { Injectable } from '@angular/core'; 
import { ActivatedRouteSnapshot, RouterStateSnapshot, Router, 
     CanActivate } from '@angular/router'; 

import { AuthService } from './auth.service'; 

@Injectable() 
export  class AuthGuard implements CanActivate { 

    constructor(private authService: AuthService, 
       private router: Router) { } 

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { 
     return this.checkLoggedIn(state.url); 
    } 

    checkLoggedIn(url: string): boolean { 
     if (this.authService.isLoggedIn()) { 
      return true; 
     } 

     // Retain the attempted URL for redirection 
     this.authService.redirectUrl = url; 
     this.router.navigate(['/login']); 
     return false; 
    } 
} 

あなたは、その後にログを必要とする任意の経路上でこのガードを使用する:これはあまりにも早く部品へのルーティングを防ぐ必要があります

   { path: 'welcome', component: WelcomeComponent }, 
       { 
        path: 'movies', 
        canActivate: [AuthGuard], 
        loadChildren: './movies/movie.module#MovieModule' 
       }, 
       { path: '', redirectTo: 'welcome', pathMatch: 'full' }, 

ルートリゾルバ

あなたが考えることができます別のオプションは、ルートリゾルバを使用することです。特定のコンポーネントにルーティングする前に、ルートのデータを取得できます。

あなたのシナリオで役立つとは思っていませんが、見て分かるかもしれません。

は、私はここで、この例を持っている:https://github.com/DeborahK/MovieHunter-routing

0

この問題は間違いなく私の認証パターンの問題を示している間、私はこの質問時につまずく人のためにここに私の調査結果を残したかったです。

問題は、角度ハンドルがどのように扱われるかにあります。 ngIf内のコンポーネントは、表示されているかどうかに関係なく、常に「初期化」されます。この現象を回避するには、代わりにテンプレートを使用してください。

は、私はテンプレートに巣<router-outlet>をすることができないためにもテンプレートを使用して私の元の認証ソリューションが動作しない、言われていること Angular4 ng-content gets built when ngIf is false

を参照してください。正しい解決策は、DeborahKが示唆するように、ロジックを変更し、ルートガードを使用することです。

関連する問題