私は最近、Angular 4 from Angular 1.5に飛び込み始めました。ユーザールートを操作し、サービスからユーザーコンポーネントにAPIデータをプルしています。
コンポーネントは、リクエストごとに更新される1. *のコントローラーとは異なり、静的なままであるように見えます。
新しいルートリクエストごとにngOnInit関数を呼び出す方法はありますか?
私のユーザーコンポーネントクラス:
// url structure: /user/:id
export class UserComponent implements OnInit {
constructor(private route: ActivatedRoute) {}
ngOnInit() {
// doesn't log new id on route change
let id = this.route.snapshot.params['id'];
console.log(id);
this.route.params
.switchMap(params => this.userService.getUser(params['id']))
.subscribe(user => {
// logs new id on route change
let id = this.route.snapshot.params['id'];
console.log(id);
this.user = user
});
}
}
[〜#〜] update [〜#〜]:
私のシナリオに最適だと思う解決策を見つけました。私の質問に対するいくつかの回答とコメント、およびさらなる調査に基づいて、ルートを購読することが進むべき道のようです。これが私の更新されたコンポーネントです:
export class UserComponent {
user;
id;
constructor(
private userService: UserService,
private route: ActivatedRoute
) {}
ngOnInit() {
this.route.params
.subscribe(params => this.handleRouteChange(params));
}
handleRouteChange(params) {
this.id = params['id'];
switch (this.id) {
case '1':
console.log('User 1');
break;
case '2':
console.log('User 2');
break;
case '3':
console.log('User 3');
break;
}
this.userService.getUser(this.id).
subscribe(user => this.user = user);
}
}
Angularは、ルートが同じであるがパラメーターが変更されている場合、新しいコンポーネントをインスタンス化するのではなく、デフォルトで同じコンポーネントを再利用することを好みます。
朗報!これはカスタマイズ可能な動作です。独自の RouteReuseStrategy
を実装することで、新しいコンポーネントインスタンスを強制的にインスタンス化できます。
export class MyRouteReuseStrategy extends DefaultRouteReuseStrategy {
shouldReuseRoute(next: ActivatedRouteSnapshot, current: ActivatedRouteSnapshot): boolean {
let name = next.component && (next.component as any).name;
return super.shouldReuseRoute(next, current) && name !== 'UserComponent';
}
}
モジュール内:
@NgModule({
...
providers:[{
provide: RouteReuseStrategy,
useClass: MyRouteReuseStrategy}]
...
})
export class AppModule {}
(このコードは多かれ少なかれ この記事 から取られています。特にname
プロパティのチェックはあまり正確ではないかもしれません...)
同じコンポーネントを復元する場合、パフォーマンスが低下する可能性があることに注意してください。したがって、スナップショットの代わりにobservablesプロパティを使用したほうがよいかもしれません。
こんにちはあなたはこのようにswitchMapを使用する必要があります:
this.sub = this.route.paramMap
.switchMap((params: ParamMap) =>
this.firebaseService.getProductsByCategory(params.get('category'))).subscribe(products => {
this.products = products;
this.count = products.length;
});
これは私のために働きます。
URLは「...?id = 1」または「../:id」のようになり、GETパラメーターが変更されるたびにコンポーネントがIDをログに記録するようにしますか?問題は ここ について話されています。私が見つけたより良い解決策は ここ です。私はそれを自分でテストしていませんが、これはうまくいくはずです。
2番目のリンクは、コンポーネント内のルート変更をサブスクライブする方法を示しています。これは基本的に、あなたがやろうとしていることだと思います。これにより、ngOnInit
内でGETパラメータの変更を処理できるようになります。最初にURLに移動したときにルートサブスクライブが実行されるかどうかわからないため、ルートイベントを処理する関数でdoCheck()
を呼び出し、ngOnInit
を変更することをお勧めします。 ngAfterContentInit
へ
ngOnInitは 変更検出 でのみ動作し、GETの変更はそれをトリガーしないようです。これは私にとって驚くべきことです。
Tl; dr-コンストラクターでルート変更イベントをサブスクライブし、発行されたイベントを処理する関数を作成します。この関数は、ngOnInit()にあるロジックを保持する必要があります。