简体   繁体   中英

Sharing data between controllers, AngularJS

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.

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');
    };
}]);

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM