How to transfer data between controllers

2019-06-09 09:14发布

问题:

I am trying to transfer data between controllers.

So this is my first controller that fetches data first when page loads using http-

function GetController($scope, $http) {
    $http.defaults.useXDomain = true;
    $http({
        method: 'POST', url: serviceUrl + '/GetProductsByCategoryOrName', headers: {
            'Authorization': apiKey
        },
        data: { "query": "grocery", "categoryId": "976759", "pageIndex": 0, "sortDirection": "asc" }
    }).then(function successCallback(response) {
        $scope.products = response.data;
    }).then(function errorCallback(error) {
    })
}

the view looks like-

 <div  ng-controller="GetController">
            <div class="mdl-cell" ng-repeat="product in products">
                 <img src="{{product.largeImage}}" />
                  <div class="mdl-card__title">
                    <h6 class="mdl-card__title-text">{{product.name}}</h6>
                </div>
            </div>
        </div>
    </div>

Where now my need is to rebind this HTML with the same request but different parameters. So I created another controller for this job-

function searchProductsController($scope, $http) {
    $http.defaults.useXDomain = true;
    $scope.searchText = "";
    $scope.submit = function () {
        $http({
            method: 'POST', url: serviceUrl + '/GetProductsByCategoryOrName', headers: {
                'Authorization': apiKey
            },
            data: { "query": $scope.searchText, "categoryId": "976759", "pageIndex": 0, "sortDirection": "asc" }
        }).then(function successCallback(response) {
            $scope.products = response.data; //how to bind this with GetController's $scope.products??
        }).then(function errorCallback(error) {
        });
    }
};

What is needed-

I want to bind $scope.products of searchProductsController to GetController's $scope.products so that it renders in view.

I don't have any idea how to do this at the moment as I am very new to angular. However, I've given a try to create service for transferring purpose but don't really have idea how to integrate it with it.

Edit-

I've edited controller methods as @Varkal suggested using service, Still couldn't get the problem resolved.

var app = angular.module("productsApp", [])
    .service("serviceProvider", function ($http) {
        this.getDatas = function getDatas(data) {
            return $http({
                method: 'POST', url: serviceUrl + '/GetProductsByCategoryOrName', headers: {
                    'Authorization': apiKey
                },
                data: data
            })
        }
        return this
    });

function GetController($scope, serviceProvider) {
    var data = { "query": "grocery", "categoryId": "976759", "pageIndex": 0, "sortDirection": "asc" };
    serviceProvider.getDatas(data).then(function (response) {
        $scope.products = response.data.data;
    });
}

function searchProductsController($scope, serviceProvider) {
    var data = { "query": $scope.searchText, "categoryId": "976759", "pageIndex": 0, "sortDirection": "asc" };

    $scope.submit = function () {
        serviceProvider.getDatas(data).then(function (response) {
            console.log(response.data.data);
            $scope.products = response.data.data;
        });
    }
};

回答1:

When you need to share things betweens controller, those things should be in a service

For example :

angular.service("datasService", function ($http) {
  this.getDatas = function getDatas() {
    return $http({
      method: 'POST', url: serviceUrl + '/GetProductsByCategoryOrName', headers: {
        'Authorization': apiKey
      },
      data: { "query": "grocery", "categoryId": "976759", "pageIndex": 0, "sortDirection": "asc" }
    })
  }
  return this
});

And in your controller :

function GetController($scope, datasService) {
  datasService.getDatas().then(function(){
    $scope.products = response.data
  }
}

This is a very simple example : you can also store your datas in the service, so call $http only once, and add a method to refresh the product list

This is the most "Angular-ly" way of share datas between controllers, but you can also use localStorage (ngStorage can help you here)



回答2:

If you have 2 views with 2 controllers, it is possible to share the $scope variables(data) between controllers through services and factory.But, the $scope variables are local to the controller itself so set the data to the service or factory to know about that particular variable.I prefer using factory, easy and smooth as butter. If you are using the service or factory in a separate file you need to include the file in index.html.

 app.controller('Ctrl1', function($scope, myService, $state) {
    $scope.variable1 = "One";
    myService.set($scope.variable1);
    $state.go('app.thepagewhereyouwanttoshare'); //go to the page where you want to share that variable.
});

app.controller('Ctrl2', function($scope, myService) {
    console.log("shared variable " + myService.get());
});
.factory('myService', function() {
    function set(data) {
        products = data;
    }

    function get() {
        return products;
    }

    return {
        set: set,
        get: get
    }

})

Also, you can use localstorage for the purpose of sharing data.localStorage comes with angularjs so no need to inject any additional dependency in the controller or app. In the controller which has to pass data:

localStorage.setItem("products",$scope.products);

In the controller where you to access data:

localStorage.getItem("products");

In your case:

function GetController($scope, $http) {
    $http.defaults.useXDomain = true;
    $http({
        method: 'POST', url: serviceUrl + '/GetProductsByCategoryOrName', headers: {
            'Authorization': apiKey
        },
        data: { "query": "grocery", "categoryId": "976759", "pageIndex": 0, "sortDirection": "asc" }
    }).then(function successCallback(response) {
        $scope.products = response.data;
        localStorage.setItem("products",$scope.products);
    }).then(function errorCallback(error) {
    })
}

function searchProductsController($scope, $http) {
    $http.defaults.useXDomain = true;
    $scope.searchText = "";
    $scope.submit = function () {
        $http({
            method: 'POST', url: serviceUrl + '/GetProductsByCategoryOrName', headers: {
                'Authorization': apiKey
            },
            data: { "query": $scope.searchText, "categoryId": "976759", "pageIndex": 0, "sortDirection": "asc" }
        }).then(function successCallback(response) {
            $scope.products = response.data; //how to bind this with GetController's $scope.products??
            $scope.productsFromGetController = localStorage.getItem("products");
        }).then(function errorCallback(error) {
        });
    }
};

Using the factory, you need to navigate to the page where you want to get the data after you set it since the data set can be overwritten by another set in another views.

FINAL UPDATE: Using service and factory

   <html>

   <head>
      <title>Angular JS Controller</title>
      <script src = "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
   </head>

   <body>
      <h2>AngularJS Sample Application</h2>

      <div ng-app = "app" >

           <div ng-controller="searchProductsController">
             <input ng-model="searchText"/>
                <button ng-click="setPlace(searchText)">Enter Search id</button>
            </div>
            <div ng-controller="GetController">
              <div ng-repeat="product in products">
                                <h3>{{product.name}}</h3>
                </div>
              </div>
      </div>


<script>
         var app = angular.module('app', []);

        app.factory("Service", function () {
          var data;
             function getdata() {
                return data;
            }
            function setdata(newdata) {
                data = newdata;
            }
            return {
                getdata: getdata,
                setdata: setdata,
            }
        }).factory("dataService",function($http){
          return{
            getComments:function (roomid){
                   if(roomid==1){
                     var data = [{"name":"alex","place":"kathmandu"},{"name":"god","place":"seattle"}];
                     return data;
                   }
                   if(roomid==2)
                   {
                     var newdata = [{"name":"newname","place":"kathmandu"},{"name":"newname2","place":"seattle"}];
                     return newdata;
                   }
              }
          }
        });
        app.controller('searchProductsController',function($scope, Service,$http,dataService) {
          var data = dataService.getComments(1);
          Service.setdata(data);
            $scope.setPlace = function (searchText) {
                var newdata = dataService.getComments(searchText);
                Service.setdata(newdata);
            }
        })
        .controller('GetController',function($scope, Service) {
            $scope.$watch(function () {
                return Service.getdata();
            }, function (value) {
                $scope.products = value;
            });
        })
              </script>

   </body>
</html>

Update regarding your unworking plunker:

It is closest i can get with the mock of your controller: http://plnkr.co/edit/p9qY1IIWyzYGLehsIOPr?p=preview