search

Home  >  Q&A  >  body text

angular.js - How to achieve real-time communication in two controllers in angularjs?

There are two controllers a and b; there is a click event in controller a. After clicking, how to display a p in control b?

For example: controller a is a menu, controller b is a content area, click on different menus in a, and control the display of different content in b,

Some effort: I tried service and factory, but I can only share data but cannot trigger it in real time

迷茫迷茫2862 days ago922

reply all(5)I'll reply

  • PHP中文网

    PHP中文网2017-05-15 16:58:29

    I have tried two methods here:
    1. Use angular’s ​​own event mechanism

    (function() {
        'use strict';
    
        angular
            .module('app.core')
            .factory('eventService', eventService);
    
        /* @ngInject */
        function eventService(logger) {
            var service = {
                on_angular_event: on_angular_event,
                trigger_angular_event: trigger_angular_event
            };
    
            return service;
    
            function on_angular_event(scope, type, f) {
                scope.$on(type, function(event, data){
                    f(data);
                    // 处理时间后阻止事件继续扩散
                    event.stopPropagation = true;
                })
            }
    
            function trigger_angular_event(scope, deriction, type, data) {
                // deriction: up, down, sibling
                if (deriction === 'up') {
                    scope.$emit(type, data);
                } else if (deriction === 'down'){
                    scope.$broadcast(type, data);
                } else if (deriction === 'sibling'){
                    scope.$parent.$broadcast(type, data);
                }
            }
        }
    })();

    Used in the controller, add a to send event notification to b:

    controller_A.$inject = [$scope, eventService];
    function controller_A($scope, eventService) {
        //send event
        //direction 根据 A 和 B 的关系来定,父子用up或down,兄弟用sibling
        eventService.trigger_angular_event($scope, direction, 'event_name', data);
    }
    
    controller_B.$inject = [$scope, eventService];
    function controller_B($scope, eventService) {
        // recv event from controller_A
        eventService.on_angular_event($scope, 'event_name', function(data){
            // do something here
        });
    }

    2. Use service to simulate callback events. The essence is to use service to save a global callback function for use between controllers

    (function() {
        'use strict';
    
        angular
            .module('app.core')
            .factory('eventService', eventService);
    
        /* @ngInject */
        function eventService(logger) {
            var onEventFunc = {};
    
            var service = {
                on: on,
                trigger: trigger
            };
    
            return service;
    
            function on(type, f) {
                onEventFunc[type] = onEventFunc[type] || [];
                var funcs = onEventFunc[type];
    
                // Todo:同一个事件可以让不同的监听者监听,但是同一个监听者的回调只能注册一次。而回调函数多用匿名函数注册,此处用toString()进行区分,效率较低。
                var exist = false;
                for (var i = 0; i < funcs.length; i++) {
                    if (funcs[i].toString() === f.toString()) {
                        exist = true;
                        break;
                    };
                };
    
                if (!exist) {
                    funcs.push(f);
                };
            }
    
            function trigger(type, data) {
                //logger.info('trigger', data);
                for (var item in onEventFunc) {
                    if (item === type) {
                        var funcs = onEventFunc[item];
                        for (var i = 0; i < funcs.length; i++) {
                            funcs[i](data);
                        };
                    }                    
                }
            }
        }
    })();

    reply
    0
  • 过去多啦不再A梦

    过去多啦不再A梦2017-05-15 16:58:29

    Hmm. You can try event bubbling and tunneling mechanisms.

    reply
    0
  • 给我你的怀抱

    给我你的怀抱2017-05-15 16:58:29

    You can take a look at this

    To be more direct, you can try $broadcast and $on, but the efficiency will be poor

    reply
    0
  • 滿天的星座

    滿天的星座2017-05-15 16:58:29

    Seeing that what is written above is not pure enough (it is mixed with other considerations), I will add a pure version.
    Demo provided

    The code is as follows

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body ng-app="myApp">
    
    <p ng-controller="aCtrl">
        <button type="button" ng-click="click()">click</button>
    </p>
    
    <p ng-controller="bCtrl">
        <p ng-if="showConfig.show">will show me</p>
    </p>
    
    <script src="../bower_components/angular/angular.min.js"></script>
    <script>
        // 通过事件,记得利用$rootScope 来广播事件。
        // 优点是解耦,也是ng的一种通讯方式. 很容易理解
        // 有人说什么性能差,效率不高之类的。 其实不是非常大的应用完全不用关注这个。 我理解就是一种js级冒泡。 性能远远小于dom操作。
    //    angular.module('myApp', []).controller('aCtrl', function ($scope, $rootScope) {
    //        $scope.click = function () {
    //            $rootScope.$broadcast('do_show');
    //        };
    //    }).controller('bCtrl', function ($scope) {
    //        $scope.showConfig = {
    //            show: false
    //        };
    //        $scope.$on('do_show', function () {
    //            $scope.showConfig.show = !$scope.showConfig.show;
    //        })
    //    });
    </script>
    <script>
        // 利用ng双向绑定技术。 通过Service提供一个Scope,具备Scope的特性,利用这个Scope 把 aCtrl bCtrl 建立联系。
        //    angular.module('myApp', []).controller('aCtrl', function ($scope, $rootScope, Service) {
        //        $scope.click = function () {
        //            Service.showConfig.show = !Service.showConfig.show;
        //        };
        //    }).controller('bCtrl', function ($scope, Service) {
        //        // 注意这里是把Scope赋值。 而非 Service.showConfig.show 一个值赋值。
        //        $scope.showConfig = Service.showConfig;
        //    }).factory('Service', function ($rootScope) {
        //        var showConfig = $rootScope.$new();
        //        showConfig.show = false;
        //        return {
        //            showConfig: showConfig
        //        };
        //    });
    </script>
    <script>
    
    </script>
    </body>
    </html>

    reply
    0
  • 黄舟

    黄舟2017-05-15 16:58:29

    1). Create an event bus to manage all events globally
    2). Use $broadcast and $emit

    reply
    0
  • Cancelreply