2

I have a directive to do 2 things: (i) it manages the visualization of some tabs in HTML, (ii) it $watches the value of the object myObj in session storage and saves this object in a variable called myData. Here there is the code:

.directive('panelManager', function(){
    return {
        restrict: 'E',
        templateUrl: 'foo.html',

        controller: ['$scope', '$window',  function($scope, $window) {
            pn = this;
            pn.tab = 1; // init

            this.selectTab = function(setTab) {
                pn.tab = setTab;
            };

            this.isSelected = function(checkTab) {
                return pn.tab === checkTab;
            };

            $scope.$watch(function () {
                return $window.sessionStorage.getItem('myObj');
            }, function (value) {
                pn.myData = JSON.parse(value);
            });
        }],
        controllerAs: 'panels'
    };
})

I have a controller to call a WS passing a property foo of the aforementioned myData, every time it changes. Here it is:

.controller('MyDataController', ['$http', function($http) {

    pdc = this;
    pdc.myResultset = [];

    pdc.getDetails = function(val) {
        return $http.get("myUrl"+val+"/").then(function(response){
              pdc.myResultset= response.data;
        });
    };
}]);

Is there a way to trigger getDetails in that controller and to pass val = MyData.foo to it every time myData changes value? In this way, I could store in myResultset the current resultset of the WS and assign it to local scope.

floatingpurr
  • 7,749
  • 9
  • 46
  • 106
  • One option is to put myData on root scope and then: 1. you can still access it from directive 2. You can watch changes in MyDataController – gandra404 Jul 20 '15 at 10:38

1 Answers1

2

You can emit from your directive, but you need the $rootScope in the associated controller. So the declaration becomes:

controller: ['$rootScope', '$scope', '$window',  function($rootScope, $scope, $window) {

Then, you could do something like this:

$scope.$watch(function () {
    return $window.sessionStorage.getItem('myObj');
}, function (value) {
    pn.myData = JSON.parse(value);
    $rootScope.$broadcast('valueChanged', pn.myData);
});

And in your controller:

.controller('MyDataController', ['$http', '$scope', function($http, $scope) {

    pdc = this;
    pdc.myResultset = [];

    pdc.getDetails = function(val) {
        return $http.get("myUrl"+val+"/").then(function(response){
            pdc.myResultset= response.data;
        });
    };

    $scope.$on('valueChanged', function(event, data) {
        pdc.getDetails(data.foo); //pass data.foo to the function
    });
}]);
Erazihel
  • 7,295
  • 6
  • 30
  • 53
  • Perfect, very cool! PS: If I had to re-use this strategy inside more controllers, could I insert `$scope.on(...);` in a factory? PPS: missing `$` before `broadcast` and before `on` – floatingpurr Jul 20 '15 at 11:09
  • 1
    Thanks for you feedback :) Of course you can ! Take a look at the following link: http://stackoverflow.com/a/16492065/4693496. – Erazihel Jul 20 '15 at 11:18
  • You are welcome! : ) Another interesting thing for readers: at the very first load `myData` is null and no `valueChanged` should happen, but for some reason `pdc.getDetails(...) ` inside `$scope.on(...);` triggers in console this error: _Cannot read property 'foo' of null_ – floatingpurr Jul 20 '15 at 11:23
  • 1
    See: http://stackoverflow.com/questions/16947771/how-do-i-ignore-the-initial-load-when-watching-model-changes-in-angularjs – Erazihel Jul 20 '15 at 11:26