5

I am trying to get $rootScope.$broadcast to refresh my view. The service is-

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
    }).factory("sharedService", function ($rootScope) {

        var mySharedService = {};

        mySharedService.values = [];

        mySharedService.passData = function (newData) {
            mySharedService.values = newData;
            $rootScope.$broadcast('dataPassed', newData);
        }

        return mySharedService;
    });

Invoking through controller-

function searchProductsController($scope, $window, serviceProvider, sharedService) {
    $scope.submit = function () {
        var data = { "query": $scope.searchText, "categoryId": "976759", "pageIndex": 0, "sortDirection": "asc" };
        serviceProvider.getDatas(data).then(function (response) {
            var result = response;
            sharedService.passData(result.data.data);
        });
    }
};

here in this controller sharedService.passData which passes new array to service method. Then it is trying to broadcast it for the changes with the line- $rootScope.$broadcast('dataPassed', newData)

I don't know why it is not broadcasting the changes to view. Is there any other way to broadcast the changes?

Note- My earlier question How to transfer data between controllers couldn't get me any help.

Edit

So far I've changed in the listeners-

mySharedService.passData = function (newData) {
    $rootScope.$broadcast('dataPassed', newData)
}
$rootScope.$on('dataPassed', function (newData) {
    mySharedService.values = newData;
})

But still can't get refreshed view.

11
  • Where is your $scpe.$on? Commented Feb 26, 2016 at 5:30
  • @Artless, How do I use it? Commented Feb 26, 2016 at 5:36
  • $broadcast would not directly async data on view...you need to set listner over broadcasted event using $on and then you can get broadacasted data inside callback function of it. And re assign data again to reflect it over scope. Commented Feb 26, 2016 at 5:48
  • @PankajParkar, I tried both the answers below, but none of worked for me. I am afraid I am doing something wrong with that. Can you please assist me Commented Feb 26, 2016 at 5:50
  • Below solutions should work..if you are not doing something wrong..do addd plunkr please Commented Feb 26, 2016 at 5:59

5 Answers 5

4

When you use $broadcast or $emit. You should have $scope.$on to listen to that event.

$scope.$on('dataPassed', function(){ //code go here });

Edit: Update working code for question requirement

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
    }).factory("sharedService", ['$rootScope', function ($rootScope) {
        var mySharedService = {
            values: [],
            setValues: function(data){
                if(data){
                    mySharedService.values.length = 0;
                    data.forEach(function(item){
                        mySharedService.values.push(item);
                    });    
                }
            }
        };
        return mySharedService;
    }]);      
function GetController($scope, serviceProvider, sharedService, $rootScope) {
    var shareData = sharedService;
    $scope.products = sharedService.values;
    $scope.shareData = sharedService;
    var data = { "query": "grocery", "categoryId": "976759", "pageIndex": 0, "sortDirection": "asc" };
    serviceProvider.getDatas(data).then(function (response) {
        sharedService.setValues(response.data.data);
    });
}
function searchProductsController($scope, $window, serviceProvider, sharedService, $rootScope) {
    $scope.submit = function () {
        var data = { "query": $scope.searchText, "categoryId": "976759", "pageIndex": 0, "sortDirection": "asc" };
        serviceProvider.getDatas(data).then(function (response) {
            sharedService.setValues(response.data.data);
        });
    }
};
Sign up to request clarification or add additional context in comments.

Comments

2

You should have put a listeners to listen to the broadbasted event. Broadcasted event would not directly update your view data directly on view html. You have to use $on over scope to bind events on scope. Inside a callback function of it. You would get an benefit to get broadcasted data & re assign that retrieve data to scope variable again to get updated binding.

Code

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;
}).factory("sharedService", ['$rootScope', function($rootScope) {

  var mySharedService = {};

  mySharedService.values = [];

  mySharedService.passData = function(newData) {
    mySharedService.values = newData;
    $rootScope.$broadcast('dataPassed', newData)
  }

  return mySharedService;
}]);

function GetController($scope, serviceProvider, sharedService, $rootScope) {
  var data = {
    "query": "grocery",
    "categoryId": "976759",
    "pageIndex": 0,
    "sortDirection": "asc"
  };
  serviceProvider.getDatas(data).then(function(response) {
    sharedService.passData(response.data.data);
  });
  //listener should register when controller loads
  $scope.$on('dataPassed', function(event, newData) {
    sharedService.values = newData;
    $scope.products = sharedService.values;
  })
}

function searchProductsController($scope, $window, serviceProvider, sharedService, $rootScope) {
    $scope.submit = function() {
      var data = {
        "query": $scope.searchText,
        "categoryId": "976759",
        "pageIndex": 0,
        "sortDirection": "asc"
      };
      serviceProvider.getDatas(data).then(function(response) {
        var result = response;
        sharedService.passData(result.data.data);
      });
    }
    //listener should register when controller loads
    $scope.$on('dataPassed', function(event, newData) {
      console.log(newData);
      sharedService.values = newData;
    })
};

3 Comments

How do I access $scope in service?
No you shouldn't.. Above code you should put inside a controller
Can you please view my js on stackoverflow group chat please? I am still not getting this work
1

You should listen what you are broadcasting :

$rootScope.$on('dataPassed', function(data){
console.log(data);
});

This reference may help : Why do we use $rootScope.$broadcast in AngularJS?

Comments

0

@Manoz as for you previous answer also, i had given you the answer. I have updated the plunker for that as well. And as for using $rootscope., you have 2 params, in which one is event and the next is the data you are broadcasting. I have mocked your api call in both the answers to make you more understand.

Here is plunker using $rootscope:http://plnkr.co/edit/MBzDMRll5Z4CjusY5QLN?p=preview

<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.run(['$rootScope', function($rootScope){
              $rootScope.test = 123;
            }]);

        app.factory("Service", function ($rootScope) {
            function passData(newData) {
              alert('i am here');
               $rootScope.$broadcast('dataPassed', newData);
            }
            return {
                passData: passData
            }
        }).factory("dataService",function($http){//mock for getting values from api
          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) {
            $scope.setPlace = function (searchText) {
                var newdata = dataService.getComments(searchText);
                Service.passData(newdata);
            }
        })
        .controller('GetController',function($scope, Service,$rootScope) {
          $rootScope.$on('dataPassed', function (event,args) {
                $scope.products = args;
            })
        })
              </script>

   </body>
</html>

Comments

0

You've made a very little, but very effective, mistake. Change your listener from this:

$rootScope.$on('dataPassed', function (newData) {
    mySharedService.values = newData;
});

To this:

$rootScope.$on('dataPassed', function ($event, newData) {
    mySharedService.values = newData;
});

On any AngularJS scope event dispatched, the first argument for every listener is one $event object.

I'm surprised that one old question, with this many answers, haven't noticed the real issue.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.