【AngularJS】Serviceを用いた画面遷移時のパラメータ受け渡し
画面遷移時にパラメータを受け渡す
AngularJSでは画面遷移が発生する(厳密には画面遷移というよりng-viewによる一部HTMLの差し替え)と、多くの場合Controllerも遷移先のViewに合わせて切り替わります。
このとき、遷移前に利用していたController上のパラメータを遷移後のControllerでも利用したいことがよくあります。
パラメータの渡し方はいくつか方法があるのですが、今回はServiceを利用したパラメータ渡しを紹介します。
なぜServiceなのか
$rootScopeを使うことでも、画面遷移時のパラメータ受け渡しは可能です。
let module = angular.module('myApp'); module.controller('ControllerA', [$rootScope, function($rootScope){ // Controller A $rootScope.value = "value"; $location.path("/b"); }]); module.controller('ControllerB', [$rootScope, function($rootScope){ // Controller B $scope.value = $rootScope.value; }]);
ただし$rootScopeは他の用途でも用いられる上、名前空間の管理をきちんと行わないと
名前が競合してパラメータが上書きされるなどの問題が発生します。
let module = angular.module('myApp'); module.controller('ControllerA', [$rootScope, function($rootScope){ // Controller A $rootScope.value = "value"; $location.path("/b"); }]); module.controller('ControllerB', [$rootScope, function($rootScope){ // Controller B // Controller Aから遷移 $scope.value = $rootScope.value; }]); module.controller('ControllerC', [$rootScope, function($rootScope){ // Controller C // 別の用途で$rootScopeを利用 $scope.value = 3; }]);
一方、画面遷移パラメータ保持専用のServiceを作ることで、そのインスタンスは「パラメータ受け渡し専用」ということを明示でき、パラメータが上書きされる危険性をぐっと抑えることができます。
実装、Usage
ディレクトリ構成は以下の通り。
. ├── index.html ├── js │ └── app.js └── view ├── a.html └── b.html
index.html
<!DOCTYPE html> <html ng-app="myApp"> <head> <meta charset="utf-8"/> <title>AngularJS - Passing Parameter to another window with Service. </title> </head> <body> <div ng-View></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-route.min.js"></script> <script src="js/app.js"></script> </body> </html>
app.js
let mod = angular.module('myApp', ['ngRoute']); // パラメータコンテナとして働くService // 実際は単一のパラメータコンテナだけを用意するのではなく、各Controller用にコンテナ用意するなどして競合を防ぐ mod.service('paramService', function(){ this.firstMessage = null; this.secondMessage = null; this.thirdMessage = null; }); // 遷移前画面に対応するController mod.controller('ACtrl', ['$scope', '$location', 'paramService', function($scope, $location, paramService){ $scope.firstMessage = "first message ."; $scope.secondMessage = "second message ."; $scope.thirdMessage = "third message ."; // ボタンを押したらパラメータをServiceにセット+画面遷移 $scope.onButtonClick = function() { paramService.firstMessage = $scope.firstMessage; paramService.secondMessage = $scope.secondMessage; paramService.thirdMessage = $scope.thirdMessage; console.log("test"); $location.path("/b"); }; }]); // 遷移後画面に対応するController mod.controller('BCtrl', ['$scope', 'paramService', function($scope, paramService){ // 受け取ったパラメータをテンプレートにセット $scope.firstMessage = paramService.firstMessage; $scope.secondMessage = paramService.secondMessage; $scope.thirdMessage = paramService.thirdMessage; }]); // ルーティング設定 mod.config(['$routeProvider', function($routeProvider) { $routeProvider .when('/', { templateUrl: 'view/a.html', controller: 'ACtrl' }) .when('/b', { templateUrl: 'view/b.html', controller: 'BCtrl' }) .otherwise({ redirectTo: '/' }); }]);
a.html
<!-- A --> <div> <p>{{firstMessage}}</p> <p>{{secondMessage}}</p> <p>{{thirdMessage}}</p> <input type=button value="nextPage" ng-click="onButtonClick()"/> </div>
b.html
<!-- B --> <div> <p>{{firstMessage}}</p> <p>{{secondMessage}}</p> <p>{{thirdMessage}}</p> </div>