web-dev-qa-db-ja.com

Angular 2パラメーター変更時にルートをリロード

現在、最初のAngular 2アプリケーションを作成しています。次の単純なテンプレートを持つOverviewComponentがあります。

<div class="row">
  <div class="col-lg-8">
    <router-outlet></router-outlet>
  </div>
  <div class="col-lg-4">
    <app-list></app-list>
  </div>
</div>

uRLにアクセスすると、/ルーターが/overviewにリダイレクトされ、ルーターアウトレット内にマップがロードされます。 <app-list>には、アプリコンポーネントの代わりに<app-detail>の表示をトリガーするクリック可能なアイテムのリストがあります。そのため、次のようなURLで参照するjsonファイルのIDを渡します:/details/:id(私のルート内)。

上記はすべて正常に機能します。リスト項目のいずれかをクリックすると詳細が表示されますが、別のリスト要素を選択しても、ビューは新しい詳細に変わりません。 URLは変更されますが、コンテンツはリロードされません。 DetailComponentの再初期化を実現するにはどうすればよいですか?

42
hGen

最初の最終リリースごとに、これは解決されています。

パラメーターが変更されたときにコンポーネントの状態を正しくリセットするように注意してください

this.route.params.subscribe(params => {
    this.param = params['yourParam'];
    this.initialiseState(); // reset and set based on new parameter this time
});
39
gpanagopoulos

コンポーネントレベルでrouteReuseStrategyを直接変更できます。

constructor(private router: Router) {

      // force route reload whenever params change;
      this.router.routeReuseStrategy.shouldReuseRoute = () => false;

}

同様に、再利用戦略はグローバルに変更できます。

これは必ずしもあなたの問題に直接対処するものではありませんが、この質問が「クエリparamsが変更された場合はangular 2 reload url」の最初の検索結果であることがわかります。

84
Nik

ここに追加する必要がある別の方法は、モジュールに RouteReuseStrategy を提供することです。

providers: [
  {
    provide: RouteReuseStrategy,
    useClass: AARouteReuseStrategy
  }
]

ルーターのデフォルトの動作は、構成が同じ場合にルートを再利用することです(この質問で:idパラメーターのみを変更する場合)。ルートを再利用しないように戦略を変更することにより、コンポーネントがリロードされ、コンポーネントのルート変更にサブスクライブする必要がなくなります。

RouteReuseStrategyの実装は次のようになります。

export class AARouteReuseStrategy extends RouteReuseStrategy {
  shouldDetach(route: ActivatedRouteSnapshot): boolean {
    return false;
  }
  store(route: ActivatedRouteSnapshot, handle: {}): void {

  }
  shouldAttach(route: ActivatedRouteSnapshot): boolean {
    return false;
  }
  retrieve(route: ActivatedRouteSnapshot): {} {
     return null;
 }
 shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
   return false; // default is true if configuration of current and future route are the same
 }
}

私もそれについてここに書いた:

https://pjsjava.blogspot.no/2018/01/angular-components-not-reloading-on.html

10

ここで提案する問題と同様の問題に対する答えがあるかどうかはわかりませんので、とにかくそれを行います:

次の方法で「偽の」リロードを達成できました。

私が基本的にやったことは、使用したい「実際の」コンポーネントにリダイレクトするコンポーネントを作成することです:

@Component({
  selector: 'camps-fake',
  template: ''
})
export class FakeComponent implements OnInit {

  constructor(private _router:Router,
              private _route:ActivatedRoute)
  { }

  ngOnInit() {
    let id:number = -1;
    this._route.params.forEach((params:Params) => {
      id = +params['id'];
    });

    let link:any[] = ['/details', id];
    this._router.navigate(link);
  }

}

そのため、リストアイテムを選択すると、ルーターは/fake/:idに移動し、URLからIDを抽出して「実際の」コンポーネントに移動します。

もっと簡単な、またはもっと派手な方法があるかもしれないことは知っていますが、偽物はあまり注目されていないので、この解決策はかなりうまくいくと思います。ページがリロードされたときの「フラッシュ」は否定的な側面ですが、私のCSS知識が到達する限り、それをカバーするための移行が行われる可能性があります。

7
hGen

受信したパラメーターの変更を検出することは可能です。私の場合、Resolveを使用して情報を読み込むため、パラメーターは必要ありません(変更があった場合のみ検出します)。これが私の最終的な解決策です。

public product: Product;
private parametersObservable: any;

constructor(private route: ActivatedRoute) {
}

ngOnInit() {
  this.parametersObservable = this.route.params.subscribe(params => {
    //"product" is obtained from 'ProductResolver'
    this.product = this.route.snapshot.data['product'];
  });
}

//Don't forget to unsubscribe from the Observable
ngOnDestroy() {
  if(this.parametersObservable != null) {
    this.parametersObservable.unsubscribe();
  }
}
5
Alexis Gamarra

子コンポーネントが新しいリンクを送信し、イベントを発行する場合、イベントを使用して解決しました。親は変更を見つけて必要なデータをリロードするリロード関数を呼び出すことができます。別のオプションは、 ルートパラメーターをサブスクライブし、変更時に検出されることです しかし、angular2の人はルーターにパラメーターを追加することを検討する必要があると思いますリロードを強制できる.navigate関数。 (forceReload = true)

2
user3728728

これが役立つことを願っています。

constructor(private router: Router){
 // override the route reuse strategy

 this.router.routeReuseStrategy.shouldReuseRoute = function(){
    return false;
 }

 this.router.events.subscribe((evt) => {
    if (evt instanceof NavigationEnd) {
       // trick the Router into believing it's last link wasn't previously loaded
       this.router.navigated = false;
       // if you need to scroll back to top, here is the right place
       window.scrollTo(0, 0);
    }
});

}
2

Angular 7プロジェクトにルーターをインポートします。

import { Router } from '@angular/router';

ルーターのオブジェクトを作成する

constructor(private router: Router) {

}

RouteReuseStrategyを使用してルーターパラメーターの変更を検出する

ngOnInit() {
    this.router.routeReuseStrategy.shouldReuseRoute = () => {
      // do your task for before route

      return false;
    }
}
2
Abhisek Dutta

現在、これは直接サポートされていません。こちらもご覧ください https://github.com/angular/angular/issues/9811

できることは

<div *ngIf="doShow" class="row">
  <div class="col-lg-8">
    <router-outlet></router-outlet>
  </div>
  <div class="col-lg-4">
    <app-list></app-list>
  </div>
</div>
doShow:boolean: true;

constructor(private _activatedRoute: ActivatedRoute, private _router:Router, private cdRef:ChangeDetectorRef) {
  _router.routerState.queryParams.subscribe(
    data => {
      console.log('queryParams', data['st']); 
      this.doShow = false;
      this.cdRef.detectChanges();
      this.doShow = true;
  });
}

(未検証)

1
this.route.paramMap.subscribe(params => {
  //fetch your new parameters here, on which you are switching the routes and call ngOnInit()
  this.ngOnInit();
 });

ParamMap内からngOnInit()を呼び出すだけで、新しく読み込まれたデータでページ全体が初期化されます。

1
cyperpunk