AngularJS help sharing data between controllers using $broadcast

随声附和 提交于 2019-12-02 23:31:48

问题


I've been trying to use $broadcast and $on but I just can't get the data to move between the two controllers.

On my main webpage i have a button which adds 4 to a var each time it's hit:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body ng-app="app">
    <div ng-controller="mainCtrl">

        <button ng-click="add(4)"> 4 </button>

    </div>
    <script src="../Scripts/angular.js"></script>
    <script src="../assets/js/angular-grid.js"></script>
    <script src="../assets/controller/gods_controller.js"></script>
    <script src="../Scripts/angular-animate.js"></script>
</body>
</html>

In my mainCtrl I have the function add() and use $broadcast to broadcast my value:

var module = angular.module("app", ["angularGrid", "ngAnimate"])

module.controller("mainCtrl", function ($scope, $rootScope) {

var total = 0

    $scope.add = function (x) {
        total += x;

        $rootScope.$broadcast('totalBroadcast', total)

    }

});

Then I have a second controller for my popup using $on to receive the broadcast:

module.controller('popUpCtrl', function ($scope) {


     $scope.$on('totalBroadcast', function(events, args){

  $scope.total = args;
  })

   })

Then my popup HTML uses the second controller and $scope.total as an expression:

    <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body ng-app="app">
    <div ng-controller="popUpCtrl">

       <p>The total is: {{total}}</p>

    </div>
    <script src="../Scripts/angular.js"></script>
    <script src="../assets/js/angular-grid.js"></script>
    <script src="../assets/controller/gods_controller.js"></script>
    <script src="../Scripts/angular-animate.js"></script>
</body>
</html>

No data seems to be passed to my second controller, the expression doesn't show anything at all.

EDIT


I have also tried using a service, HTML's above remain the same but now I've added a service

module.factory('myService', function () {

    var total = 0;

    var setTotal = function (x) {
        total = x;
    }

    var getTotal = function () {
        return total;
    };

    return {
        setTotal: setTotal,
        getTotal: getTotal
    }


    });

My main controller and ad function are now:

 module.controller("mainCtrl", function ($scope, myService) {

    var total = 0

    $scope.add = function (x) {

        myService.setTotal(x)
    }

 });

and my popupCtrl controller is now this :

module.controller('popUpCtrl', function ($scope, myService) {


    $scope.total = myService.getTotal();

})

{{total}} in my popup is now being expressed as the "0" which var total is equal to in my service. So the data is now being transferred using the service, but the setTotal() method isn't setting the var as instructed by the add() function now. I have injected my service as a dependency to both controllers.


回答1:


Its a very bad practice to add watches or broadcast for sharing your data between controllers, do it for injecting a common service in both controllers.

Services provide an easy way for us to share data and functionality throughout our app. The services we create are singletons that can be injected into controllers and other services, making them the ideal place for writing reusable code.

Follow its link https://thinkster.io/a-better-way-to-learn-angularjs/services




回答2:


The reason you are getting zero is that you controller is assigning to value of myService.getTotal() only when it is loading. That means that when you change the total variable it won't be updated.

You need to $watch for the updates:

$scope.$watch(function () {
    return myService.getTotal();
}, function (newVal) {
    $scope.total = newVal;
});

Besides, it looks like you are re initializing your app with new pages. This is not how angular works. Read about angular route and then try to do what I suggested here. It should work if you make it a single page app.




回答3:


I did find a solution to my initial question, which was to use localStorage.setItem("num", "num") to store the data in the browser. It seems this was developed specifically to share data between tabs/windows, and so is accessible via localStorage.getItem("num").

This answers my original question, however I would now like the total to be updated dynamically. At the moment it is only updated upon refresh. Any tips would be appreciated.


EDIT (ANSWER TO ABOVE)

By using this event listener in my second popup -

window.addEventListener('storage', function (event) {
        $scope.total = parseInt(event.newValue);
        $scope.$apply();
    });

I was able to access the storage and bind it to an expression in my HTML. Bear in mind $scope.apply() needs to be called here because total is outside of the scope.

More detail here - https://developer.apple.com/library/safari/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/Name-ValueStorage/Name-ValueStorage.html



来源:https://stackoverflow.com/questions/32650025/angularjs-help-sharing-data-between-controllers-using-broadcast

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!