Reputation: 3877
I'm facing the following situation in my Angular application and I would like to have some advices here.
I have a page where I show some products, this page is managed by a controller called 'ProductsController'. This controller has a method called 'showProductDetails' which is called once the user clicks on a specific product, and the goal of this method is just to retrieve the details of the product and to display these details in a modal panel. Nothing really special until here. The problem is that because of modularity I would like to attach a different controller to the modal panel, and to manage all the logic of this modal panel in the new controller, in this case 'ProductDetailController'. The problem is that I retrieve the data of the product before opening the modal panel, but as I retrieve this data in the scope of the first controller, from the second controller I cannot access to the product that I have previously retrieved. I've been told that to share data between controllers in angularJs is done through services, but I don't see how a stateless service can help me here.
Here is my code to understand better the situation:
The first controller:
app.controller('ProductsController', ['$scope','productsFactory','commonFactory','productsFactoryHelper','$filter','$modal',function ($scope,productsFactory,commonFactory,productsFactoryHelper,$filter,$modal)
{
$scope.showProductDetails = function (size,product) {
$scope.showLoader('Loading the details of the product. Please wait...');
productsFactoryHelper.Product.query({id:product.id},function(response)
{
$scope.selectedProduct=response;
$scope.hideLoader();
var modalInstance = $modal.open({
templateUrl: 'productDetail.html',
controller: 'ProductDetailController',
size: size
});
},function(error)
{
commonFactory.Pop('error','This product is not available at this moment. Please try again later. If the problem persists contact a system administrator');
$scope.hideLoader();
});
};
_init();
}]);
And the second controller:
app.controller('ProductDetailController',['$scope','$modalInstance', function ($scope, $modalInstance) {
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}]);
So basically the question is how can access from the 'ProductDetailController' to the object 'selectedProduct' which is in the scope of the 'ProductsController'.
Thank you for your help.
Upvotes: 1
Views: 148
Reputation: 5254
Services are indeed the answer for you, or you can use pure eventing if you do not need to access the data more then once.
Pure Eventing
app.controller('parentCtrl', function($scope) {
// Do something
// Action completed
@scope.$emit('someactionComplete', data);
});
app.controller('childCtrl', function($scope) {
$scope.$on('someactionComplete', function(data) {
// Process data
});
});
Using a service. The advantage of using a service is that the data is persisted.
app.controller('parentCtrl', function($scope, MyService) {
// Do something
// Action completed
MyService.setData(data);
@scope.$emit('someactionComplete');
});
app.controller('childCtrl', function($scope) {
$scope.$on('someactionComplete', function() {
MyService.getData(data);
});
});
You could further enhance this were the service loaded the data and returns a promise in the getter.
Upvotes: 0
Reputation: 2531
Use resolve of the $modal to send your data to the new controller like below.
app.controller('ProductsController', ['$scope','productsFactory','commonFactory','productsFactoryHelper','$filter','$modal',function ($scope,productsFactory,commonFactory,productsFactoryHelper,$filter,$modal)
{
$scope.showProductDetails = function (size,product) {
$scope.showLoader('Loading the details of the product. Please wait...');
productsFactoryHelper.Product.query({id:product.id},function(response)
{
$scope.selectedProduct=response;
$scope.hideLoader();
var modalInstance = $modal.open({
templateUrl: 'productDetail.html',
controller: 'ProductDetailController',
size: size,
resolve:{
"selectedProduct":response
}
});
},function(error)
{
commonFactory.Pop('error','This product is not available at this moment. Please try again later. If the problem persists contact a system administrator');
$scope.hideLoader();
});
};
_init();
}]);
I dont know about the producfactory helper product query has a promise if it has a promise you can use like this..
$scope.showProductDetails = function (size,product) {
$scope.showLoader('Loading the details of the product. Please wait...');
var modalInstance = $modal.open({
templateUrl: 'productDetail.html',
controller: 'ProductDetailController',
size: size,
resolve:{
"selectedProduct":productsFactoryHelper.Product.query({id:product.id})
}
});
};
And in the ProductDetailController you can inject this selectedProduct like below
app.controller('ProductDetailController',['$scope','$modalInstance','selectedProduct ' function ($scope, $modalInstance,selectedProduct ) {
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}]);
Upvotes: 2
Reputation: 103
This can indeed be done through services, since they are stateless and keep their data once instantiated.
function productService($http) {
this.products = [];
this.loadProducts() {
$http.get('/url/to/your/product/api').then(function(err, data) {
this.products = data.products;
});
};
this.getProducts = function() {
return this.products;
}
}
angular
.module('yourModule')
.service('productService', productService);
You can then just inject productService
in both controllers, load the products using productService.loadProducts()
, and get them using productService.getProducts()
.
This is just an example. Services can be used to share any kind of data.
Upvotes: 0