web-dev-qa-db-ja.com

Angular ui-routerを使用して、状態を変更せずにURLクエリパラメーターを設定します

ページを更新するときに状態を維持するために、AngularJSのui-routerを使用して、クエリパラメーターを変更してアドレスバーのURLを更新する方法を教えてください。

現在、入力が変更されるたびに$state.transitionTo('search', {q: 'updated search term'})を使用していますが、問題はコントローラーをリロードし、ウィンドウを再描画し、テキスト入力フォーカスを失うことです。

StateParamsを更新してウィンドウURLに同期する方法はありますか?

65
Petrus Theron

i-router 0.2.14に更新するまで、.transitionToで問題が発生していました。 0.2.14は、次のような呼び出しを使用して、ロケーションバーを適切に変更します(コントローラーをリロードせずに)。

$state.transitionTo('search', {q: 'updated search term'}, { notify: false });
78
pmont

編集:これを今日もう少し試してみて、angular ui-routerにはネイティブrouterProvider: "reloadOnSearch"と同様のオプションがあることに気付きました。

https://github.com/angular-ui/ui-router/wiki/Quick-Reference#options-1

デフォルトではtrueに設定されていますが、状態でfalseに設定した場合、クエリパラメータが変更されても状態は変更されません。その後、$location.search(params);または$location.search('param', value);を呼び出すとURLが変更されますが、ui-routerはコントローラー/ビュー全体を再構築しません。また、ルートスコープで$locationChangeStartイベントをリッスンして、アプリ内で前後の履歴アクションを処理する必要があります。これらも状態の変化を引き起こさないためです。

また、コントローラーのスコープで$stateChangeSuccessイベントをリッスンして、ページ/ルートの初期読み込みをキャプチャしています。

(URLの変更だけでなく)パスの変更でこの機能を使用するためのgithubについての議論があります: https://github.com/angular-ui/ui-router/issues/125 but I haven '私の使用例はクエリ文字列パラメータに固有であるため、tはまったくテストしていません。

私の答えの以前のバージョンでは、このgithubの問題について言及していました。

https://github.com/angular-ui/ui-router/issues/562

しかし、それはわずかに別の問題であり、特に非モーダル状態が変化することなく、ある状態のモーダルを別の状態の上に表示します。その問題でパッチを試しましたが、URLの変更時に状態全体がリロードされるのを防ぐためのものではないことは明らかです。

28
Jay Klehr

2015年5月19日更新

Ui-router 0.2.15の時点で、クエリパラメータの変更時に状態をリロードする問題は解決されました。ただし、新しい更新プログラムは、クエリAPIを使用した履歴APIの前後の機能を破壊しました。そのための回避策を見つけることができませんでした。

オリジナル

ジェイの答えは私には役に立たず、他のたくさんの答えもしませんでした。 $locationChangeStartをリ​​ッスンしようとすると、ブラウザーの履歴を前後に移動しようとするとコードが2回実行されるため、問題が発生しました。1回は新しい状態が変更され、もう1回は$loationChangeStart.

reloadOnSearch=falseを使用してみましたが、URLパスが変更された場合でも 状態の変更を防ぐ です。だから私は最終的に次のことを行うことで動作するようになりました:

$location.search()を変更してクエリパラメータを更新する場合は、 "hack" を使用して、検索時の再読み込みを一時的に無効にし、クエリパラメータを設定し、再読み込みを再度有効にします。

$state.current.reloadOnSearch = false;

$location.search('query', [1,2]);

$timeout(function () {
  $state.current.reloadOnSearch = undefined;
});

これにより、クエリパラメータの変更が状態をリロードせず、URLパスの変更が状態を適切にリロードすることが保証されます。

ただし、クエリパラメータがurlの一部である場合、ブラウザの履歴を取得して状態を変更することはできませんでした(クエリパラメータがいつURLを再読み取りするかを知るために必要です)。そのため、各クエリパラメータの名前を stateurlプロパティに追加する必要もありました。

$locationProvider.html5Mode(true);

$stateProvider
  .state('home', {
    url: '/?param1&param2&param3',
    templateUrl: 'home.html',
    controller: 'homeCtrl as home',
  });

この方法でリストされている場合、URLのパラメーター名はオプションですが、これらのパラメーター名を変更すると、ブラウザーの[戻る]ボタンと[進む]ボタンを押すと状態がリロードされます。

うまくいけば、他の人がこれが便利であり、それを行う方法を理解するのに数日かかることはありません(私がやったように)。

27
Steven Lambert