Reputation: 762
I have a button in my application that opens a Modal. This modal is configured in the UI Routes state to be oppened with a new url.
In the Modals Controller I need to access the parent $scope. In the parent $scope I have an array that needs be accessed in the child state called: todolist.add.
Why I need to access the parent $scope? Because I want to manipulate the parent $scope data without call the server again.
What is the best way to access the parent scope in UI Router?
// routes
$stateProvider
.state('todolist', {
url: '/todo-list',
views: {
'@': {
...,
controller: 'ListsController'
}
}
})
.state('todolist.add', {
url: '/list/add',
onEnter: ['$state', '$uibModal', function ($state, $uibModal) {
$uibModal.open({
...,
controller: 'FormListModalController' // <- in this controller I need to access the $scope from the parent
}).result.finally(function () {
...
});
}]
})...
.
.controller('ListsController', function ($scope, ...) {
$scope.lists = []; // there are data in this $scope array
});
.
.controller('FormListModalController', function ($scope, ...) {
$scope.$parent.todolist.lists; // <- in this Modal's Ctrl I need to access the parent $scope (ListsController)
});
Upvotes: 0
Views: 390
Reputation: 676
What you are trying to do can't really work. Because your 'todolist.add' state controller isn't shared with your modal (popup) controller. In your case, 'todolist.add' has an empty controller and your modal instantiated onEnter uses FormListModalController controller.
SOLUTION 1: STATE PARAMS + RESOLVE
I solved this, by doing a data copy from the $scope between the two states and the modal: parent state -> child state -> modal.
Please find below a sample where :
home.popup is the child state that opens a popup
angular.module('test', [ 'ui.bootstrap', 'ui.router' ]);
angular.module('test').config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider, $stickyStateProvider, $locationProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider
.state('home', {
url : '/home',
templateUrl : './home.html',
controller : 'homeController'
})
.state('home.popup', {
url : '/popup',
params : {tocopy: null},
onEnter: ['$state', '$stateParams', '$uibModal', function ($state, $stateParams, $uibModal) {
$uibModal.open({
templateUrl: './popup.html',
controller: 'popupController',
resolve: {
tocopy: function() {
return $stateParams.tocopy;
}
}
}).result.finally(function() {
$state.go('^');
});
}]
})
}]);
angular.module('test').controller('homeController', function($scope, $state) {
$scope.tocopy = "hello";
$scope.openPopup = function() {
$state.go('home.popup', { tocopy: $scope.tocopy});
};
});
angular.module('test').controller('popupController', function($scope, $state, tocopy) {
$scope.tocopy = tocopy;
});
The trick is to use:
SOLUTION 2: STORAGE SERVICE
In case of a large data set, aNother solution can consist in storing the data in a service which will be accessible by any controllers.
angular.module('test', [ 'ui.bootstrap', 'ui.router' ]);
angular.module('test').config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider, $stickyStateProvider, $locationProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider
/*******************************************************
* HOME
*******************************************************/
.state('home', {
url : '/home',
templateUrl : './home.html',
controller : 'homeController'
})
.state('home.popup', {
url : '/popup',
onEnter: ['$state', '$stateParams', '$uibModal', function ($state, $stateParams, $uibModal) {
$uibModal.open({
templateUrl : './popup.html',
controller : 'popupController',
windowClass : 'center-modal'
}).result.finally(function() {
$state.go('^');
});
}]
})
}]);
angular.module('test').service('storageService', function () {
var data;
return {
getData: function() { return data; },
setData: function(value) { data = value; }
};
});
angular.module('test').controller('homeController', function($scope, $state, storageService) {
$scope.tocopy = "hello";
$scope.openPopup = function() {
storageService.setData($scope.tocopy);
$state.go('home.popup');
};
});
angular.module('test').controller('popupController', function($scope, $state, storageService) {
$scope.tocopy = storageService.getData();
});
Code: I pushed my example in GitHub if you want to take a look: https://github.com/gjeanmart/stackexchange/tree/master/43823794
Upvotes: 1