翻訳辞書:
-ビュー-テンプレート
-ルート-ルート、パス
-ナビゲーション-移行
ルーティングは、最小限のコードでパターンをAngularJSコントローラーに関連付けることができる優れたツールです。
ユーザーは指定されたパスに直接アクセスできますが、重要なアクション(データの保存など)を完了する前に移行を開始する可能性があります。 このような状況では、移行をキャンセルして、作業を終了するか、データの損失について警告するかをユーザーに尋ねることができます。 この記事では、このようなタスクを実装するために使用できる手法について説明します。
$ LocationChangeStartイベント
AngularJSアプリケーションで遷移が発生すると、いくつかのイベントが発生します。 それらの1つは$ locationChangeStartと呼ばれ、もう1つは$ routeChangeStartです(実際にはさらにいくつかあります)。 現在(バージョン1.2)、$ routeChangeStartイベントは遷移をキャンセルする機会を提供しませんが、$ locationChangeStartはこれに非常に適しています。 AngularJSコードを見ると、$ browserオブジェクトのonUrlChange()メソッドが呼び出されたときの$ locationChangeStartイベントの発生を示す次のセクションがあります。
$browser.onUrlChange(function (newUrl) { if ($location.absUrl() != newUrl) { if ($rootScope.$broadcast('$locationChangeStart', newUrl, $location.absUrl()).defaultPrevented) { $browser.url($location.absUrl()); return; } $rootScope.$evalAsync(function () { var oldUrl = $location.absUrl(); $location.$$parse(newUrl); afterLocationChange(oldUrl); }); if (!$rootScope.$$phase) $rootScope.$digest(); } });
コードの最も重要な部分は、$ broadcastを呼び出すことです。 この呼び出しは、$ locationChangeStartイベントをすべての子スコープにディスパッチします。これにより、子が場所の変更を通知できるようになります。 このイベントを処理するには、$ rootScope.on()関数を使用できます。 たとえば、コントローラーの起動直後に呼び出される関数に$ on()の呼び出しを追加しました。
function init() { //initialize data here.. //Make sure they're warned if they made a change but didn't save it //Call to $on returns a "deregistration" function that can be called to //remove the listener (see routeChange() for an example of using it) onRouteChangeOff = $rootScope.$on('$locationChangeStart', routeChange); }
このコードは$ locationChangeStartイベントを予期し、発生時にrouteChange()関数を呼び出します。 $ on関数の戻り値は「キャンセル待ち」関数で、イベントの待機を停止するために呼び出すことができます。 この例では、onRouteChangeOffと呼ばれます(コントローラーで使用可能)。 使用方法はすぐにわかります。
ルート横断をキャンセル
コールバック関数routeChange()は、$ locationChangeStartイベントによってトリガーされ、ユーザーに警告ダイアログを表示します。
routeChange()関数のコードは次のとおりです。
function routeChange(event, newUrl) { //Navigate to newUrl if the form isn't dirty if (!$scope.editForm.$dirty) return; var modalOptions = { closeButtonText: 'Cancel', actionButtonText: 'Ignore Changes', headerText: 'Unsaved Changes', bodyText: 'You have unsaved changes. Leave the page?' }; modalService.showModal({}, modalOptions).then(function (result) { if (result === 'ok') { onRouteChangeOff(); //Stop listening for location changes $location.path(newUrl); //Go to page they're interested in } }); //prevent navigation by default since we'll handle it //once the user selects a dialog option event.preventDefault(); return; }
この関数のパラメーターでは、イベントオブジェクトと、ユーザーがたどろうとしている新しいルートを確認できます。 テンプレートを変更する前にデータ損失についてユーザーに通知する必要があるため、イベントオブジェクトを使用して遷移をキャンセルします。 関数の最後にあるevent.preventDefault()の呼び出しに注目してください。
modalService.showModal()関数を呼び出すと、ダイアログボックスが表示されます(Angular UI Bootstrapの$モーダルサービスのラッパーとして機能するパーソナライズされたmodalServiceについての以前の投稿をご覧ください)。
ユーザーが「変更を無視」を選択した場合、ユーザーの変更はキャンセルされ、アプリケーションは必要なルートをたどります。 これは、onRouteChangeOff()関数を呼び出して$ locationChangeStartイベントの待機を無効にすることで発生します(この関数は$ on関数を呼び出すことで返されることを忘れないでください)。
次に、$ location.path(newUrl)が呼び出され、指定されたテンプレートへの移行が処理されます。 ユーザーがアクションをキャンセルすると、現在のテンプレートのままになります。
結論
移行をキャンセルするための鍵は、$ locationChangeStartイベントがどのように機能するかを理解することです。
将来、同様のタスクが$ routeChangeStartイベントの助けを借りて解決できることを願っていますが、現時点では上記のコードが完全に機能します。
Githubで利用可能な顧客管理アプリケーション (特にcustomerEditテンプレート)でこのコードがどのように機能するかの例を見ることができます。 アプリの詳細についてはこちらをご覧ください。