Cách chính xác để giao tiếp giữa các bộ điều khiển trong AngularJS là gì?


473

Cách chính xác để giao tiếp giữa các bộ điều khiển là gì?

Tôi hiện đang sử dụng một fudge khủng khiếp liên quan đến window:

function StockSubgroupCtrl($scope, $http) {
    $scope.subgroups = [];
    $scope.handleSubgroupsLoaded = function(data, status) {
        $scope.subgroups = data;
    }
    $scope.fetch = function(prod_grp) {
        $http.get('/api/stock/groups/' + prod_grp + '/subgroups/').success($scope.handleSubgroupsLoaded);
    }
    window.fetchStockSubgroups = $scope.fetch;
}

function StockGroupCtrl($scope, $http) {
    ...
    $scope.select = function(prod_grp) {
        $scope.selectedGroup = prod_grp;
        window.fetchStockSubgroups(prod_grp);
    }
}

36
Hoàn toàn moot, nhưng trong Angular, bạn nên luôn luôn sử dụng cửa sổ $ thay vì đối tượng cửa sổ JS gốc. Bằng cách này, bạn có thể loại bỏ nó trong các bài kiểm tra của mình :)
Dan M

1
Xin vui lòng xem các bình luận trong câu trả lời dưới đây từ tôi về vấn đề này. $ phát sóng không còn đắt hơn $ phát ra. Xem liên kết jsperf tôi đã tham chiếu ở đó.
bảo vệ zumalififard

Câu trả lời:


457

Chỉnh sửa : Vấn đề được giải quyết trong câu trả lời này đã được giải quyết trong phiên bản angular.js 1.2.7 . $broadcastbây giờ tránh sủi bọt trên phạm vi chưa đăng ký và chạy nhanh như $ phát ra. $ biểu diễn phát sóng giống hệt với $ phát ra với góc 1.2.16

Vì vậy, bây giờ bạn có thể:

  • sử dụng $broadcasttừ$rootScope
  • lắng nghe bằng cách sử dụng $on từ địa phương$scope cần biết về sự kiện này

Câu trả lời gốc bên dưới

Tôi khuyên bạn không nên sử dụng $rootScope.$broadcast+ $scope.$onmà là $rootScope.$emit+ $rootScope.$on. Cái trước có thể gây ra vấn đề hiệu suất nghiêm trọng như được nêu ra bởi @numan. Đó là bởi vì sự kiện sẽ bong bóng xuống qua tất cả các phạm vi.

Tuy nhiên, cái sau (sử dụng $rootScope.$emit+ $rootScope.$on) không bị như vậy và do đó có thể được sử dụng như một kênh liên lạc nhanh!

Từ các tài liệu góc của $emit:

Gửi một tên sự kiện trở lên thông qua hệ thống phân cấp phạm vi thông báo đã đăng ký

Vì không có phạm vi ở trên $rootScope, không có bong bóng xảy ra. Hoàn toàn an toàn khi sử dụng $rootScope.$emit()/ $rootScope.$on()làm EventBus.

Tuy nhiên, có một gotcha khi sử dụng nó từ bên trong Bộ điều khiển. Nếu bạn liên kết trực tiếp $rootScope.$on()từ bên trong bộ điều khiển, bạn sẽ phải tự dọn sạch ràng buộc khi địa phương của bạn $scopebị phá hủy. Điều này là do các bộ điều khiển (trái ngược với các dịch vụ) có thể được khởi tạo nhiều lần trong suốt vòng đời của một ứng dụng dẫn đến các ràng buộc tóm tắt cuối cùng tạo ra rò rỉ bộ nhớ ở mọi nơi :)

Để unregister, chỉ cần lắng nghe trên của bạn $scope's $destroysự kiện và sau đó gọi hàm đã được trả về bởi $rootScope.$on.

angular
    .module('MyApp')
    .controller('MyController', ['$scope', '$rootScope', function MyController($scope, $rootScope) {

            var unbind = $rootScope.$on('someComponent.someCrazyEvent', function(){
                console.log('foo');
            });

            $scope.$on('$destroy', unbind);
        }
    ]);

Tôi có thể nói, đó thực sự không phải là một điều cụ thể góc cạnh vì nó cũng áp dụng cho các triển khai EventBus khác, rằng bạn phải dọn sạch các tài nguyên.

Tuy nhiên, bạn có thể làm cho cuộc sống của bạn dễ dàng hơn cho những trường hợp đó. Chẳng hạn, bạn có thể vá khỉ $rootScopevà cho nó $onRootScopeđăng ký các sự kiện phát ra trên $rootScopenhưng cũng trực tiếp dọn sạch trình xử lý khi cục bộ $scopebị phá hủy.

Cách sạch nhất để khỉ vá phương pháp $rootScopecung cấp $onRootScopephương pháp như vậy là thông qua một người trang trí (một khối chạy có thể sẽ làm tốt như vậy nhưng pssst, đừng nói với ai)

Để đảm bảo $onRootScopetài sản không xuất hiện bất ngờ khi liệt kê $scopechúng tôi sử dụng Object.defineProperty()và đặt enumerablethành false. Hãy nhớ rằng bạn có thể cần một shim ES5.

angular
    .module('MyApp')
    .config(['$provide', function($provide){
        $provide.decorator('$rootScope', ['$delegate', function($delegate){

            Object.defineProperty($delegate.constructor.prototype, '$onRootScope', {
                value: function(name, listener){
                    var unsubscribe = $delegate.$on(name, listener);
                    this.$on('$destroy', unsubscribe);

                    return unsubscribe;
                },
                enumerable: false
            });


            return $delegate;
        }]);
    }]);

Với phương pháp này, mã điều khiển từ trên có thể được đơn giản hóa thành:

angular
    .module('MyApp')
    .controller('MyController', ['$scope', function MyController($scope) {

            $scope.$onRootScope('someComponent.someCrazyEvent', function(){
                console.log('foo');
            });
        }
    ]);

Vì vậy, như là kết quả cuối cùng của tất cả điều này, tôi khuyên bạn nên sử dụng $rootScope.$emit+ $scope.$onRootScope.

Btw, tôi đang cố gắng thuyết phục đội ngũ góc cạnh để giải quyết vấn đề trong lõi góc. Có một cuộc thảo luận đang diễn ra ở đây: https://github.com/angular/angular.js/issues/4574

Dưới đây là một jsperf cho thấy mức độ ảnh hưởng hoàn hảo $broadcastmang đến cho bảng trong một kịch bản hợp lý chỉ với 100 $scopegiây.

http://jsperf.com/rootscope-emit-vs-rootscope-broadcast

kết quả jsperf


Tôi đang cố gắng thực hiện tùy chọn thứ 2 của bạn, nhưng tôi đang gặp lỗi: Uncaught TypeError: Không thể xác định lại thuộc tính: $ onRootScope ngay tại nơi tôi đang thực hiện Object.defineProperty ....
Scott

Có lẽ tôi đã làm hỏng cái gì đó khi tôi dán nó ở đây. Tôi sử dụng nó trong sản xuất và nó hoạt động rất tốt. Tôi sẽ xem vào ngày mai :)
Christoph

@Scott Tôi đã dán nó nhưng mã đã chính xác và chính xác là những gì chúng tôi sử dụng trong sản xuất. Bạn có thể kiểm tra lại rằng bạn không có lỗi đánh máy trên trang web của mình không? Tôi có thể xem mã của bạn ở đâu đó để giúp khắc phục sự cố không?
Christoph

@Christoph có cách nào tốt để làm trình trang trí trong IE8 không, vì nó không hỗ trợ Object.defineProperty trên các đối tượng không phải DOM?
joshschreuder

59
Đây là một giải pháp rất thông minh cho vấn đề, nhưng nó không còn cần thiết nữa. Phiên bản mới nhất của Angular (1.2.16), và có lẽ trước đó, đã khắc phục vấn đề này. Bây giờ $ Broadcast sẽ không truy cập vào mọi bộ điều khiển hậu duệ mà không có lý do. Nó sẽ chỉ đến thăm những người thực sự lắng nghe sự kiện này. Tôi đã cập nhật jsperf được tham chiếu ở trên để chứng minh rằng sự cố hiện đã được khắc phục: jsperf.com/rootscope-emit-vs-rootscope-broadcast/27
zumalifeguard

107

Các đầu câu trả lời ở đây là một công trình xung quanh từ một vấn đề góc mà không còn tồn tại (ít nhất là trong các phiên bản> 1.2.16 và "có lẽ trước đó") như @zumalifeguard đã đề cập. Nhưng tôi vẫn đọc tất cả những câu trả lời này mà không có giải pháp thực tế.

Dường như với tôi rằng câu trả lời bây giờ nên là

  • sử dụng $broadcasttừ$rootScope
  • lắng nghe bằng cách sử dụng $on từ địa phương$scope cần biết về sự kiện này

Vì vậy, để xuất bản

// EXAMPLE PUBLISHER
angular.module('test').controller('CtrlPublish', ['$rootScope', '$scope',
function ($rootScope, $scope) {

  $rootScope.$broadcast('topic', 'message');

}]);

Và đăng ký

// EXAMPLE SUBSCRIBER
angular.module('test').controller('ctrlSubscribe', ['$scope',
function ($scope) {

  $scope.$on('topic', function (event, arg) { 
    $scope.receiver = 'got your ' + arg;
  });

}]);

Plunker

Nếu bạn đăng ký listener trên địa phương $scope, nó sẽ được phá hủy tự động bằng cách $destroyriêng của mình khi bộ điều khiển đi kèm được lấy ra.


1
Bạn có biết nếu cùng một mô hình có thể được sử dụng với controllerAscú pháp? Tôi đã có thể sử dụng $rootScopetrong thuê bao để lắng nghe sự kiện này, nhưng tôi chỉ tò mò nếu có một mô hình khác.
edhedges

3
@edhedges Tôi đoán bạn có thể tiêm một $scopecách rõ ràng. John Papa viết về các sự kiện là một "ngoại lệ" đối với quy tắc thông thường của ông là $scope"tránh" các bộ điều khiển của mình (tôi sử dụng dấu ngoặc kép vì như ông Controller Asvẫn đề cập $scope, nó chỉ nằm dưới nắp ca-pô).
chắc chắn nhất là

Bởi dưới nắp ca-pô, bạn có nghĩa là bạn vẫn có thể lấy nó qua tiêm?
edhedges

2
@edhedges Tôi đã cập nhật câu trả lời của mình bằng một controller ascú pháp thay thế theo yêu cầu. Tôi hy vọng đó là những gì bạn có ý nghĩa.
tốt nhất vào

3
@dsdsdsdsd, dịch vụ / nhà máy / nhà cung cấp sẽ tồn tại mãi mãi. Luôn có một và chỉ một trong số họ (singletons) trong một ứng dụng Angular. Mặt khác, các bộ điều khiển được gắn với chức năng: các thành phần / chỉ thị / ng-điều khiển, có thể được lặp lại (như các đối tượng được tạo từ một lớp) và chúng đến và đi khi cần thiết. Tại sao bạn muốn một bộ điều khiển và bộ điều khiển của nó tồn tại khi bạn không cần nó nữa? Đó là định nghĩa của rò rỉ bộ nhớ.
chắc chắn nhất vào


42

Vì định nghĩa là có vấn đề tương thích trình duyệt, tôi nghĩ chúng ta có thể nghĩ về việc sử dụng một dịch vụ.

angular.module('myservice', [], function($provide) {
    $provide.factory('msgBus', ['$rootScope', function($rootScope) {
        var msgBus = {};
        msgBus.emitMsg = function(msg) {
        $rootScope.$emit(msg);
        };
        msgBus.onMsg = function(msg, scope, func) {
            var unbind = $rootScope.$on(msg, func);
            scope.$on('$destroy', unbind);
        };
        return msgBus;
    }]);
});

và sử dụng nó trong bộ điều khiển như thế này:

  • bộ điều khiển 1

    function($scope, msgBus) {
        $scope.sendmsg = function() {
            msgBus.emitMsg('somemsg')
        }
    }
  • bộ điều khiển 2

    function($scope, msgBus) {
        msgBus.onMsg('somemsg', $scope, function() {
            // your logic
        });
    }

7
+1 cho việc hủy đăng ký tự động khi phạm vi bị hủy.
Federico Nafria

6
Tôi thích giải pháp này. 2 thay đổi tôi đã thực hiện: (1) cho phép người dùng chuyển 'dữ liệu' sang tin nhắn phát ra (2) thực hiện việc chuyển 'phạm vi' tùy chọn để có thể sử dụng điều này trong các dịch vụ đơn lẻ cũng như bộ điều khiển. Bạn có thể thấy những thay đổi được triển khai tại đây: gist.github.com/turtlemonvh/10686980/ mẹo
turtlemonvh


15

Trên thực tế, việc sử dụng phát và phát là không hiệu quả vì sự kiện bong bóng lên xuống phân cấp phạm vi có thể dễ dàng làm suy giảm hiệu suất đóng chai cho một ứng dụng phức tạp.

Tôi sẽ đề nghị sử dụng một dịch vụ. Đây là cách gần đây tôi đã triển khai nó trong một trong các dự án của mình - https://gist.github.com/3384419 .

Ý tưởng cơ bản - đăng ký xe buýt pubsub / sự kiện như một dịch vụ. Sau đó tiêm eventbus đó bất cứ khi nào bạn cần đăng ký hoặc xuất bản các sự kiện / chủ đề.


7
Và khi không cần bộ điều khiển nữa, làm thế nào bạn tự động hủy đăng ký nó? Nếu bạn không làm điều này, vì đóng bộ điều khiển sẽ không bao giờ bị xóa khỏi bộ nhớ và bạn vẫn sẽ cảm nhận được thông báo cho nó. Để tránh điều này, bạn sẽ cần phải loại bỏ bằng tay. Sử dụng $ vào điều này sẽ không xảy ra.
Renan Tomal Fernandes

1
đó là một điểm công bằng Tôi nghĩ rằng nó có thể được giải quyết bằng cách bạn kiến ​​trúc ứng dụng của bạn. trong trường hợp của tôi, tôi có một ứng dụng trang duy nhất để nó trở thành một vấn đề dễ hiểu hơn. đã nói rằng, tôi nghĩ rằng điều này sẽ sạch sẽ hơn nhiều nếu các góc vòng có móc vòng đời thành phần nơi bạn có thể nối dây / những thứ không mong muốn như thế này.
numan salati

6
Tôi chỉ để lại ở đây như không ai nói trước đây. Sử dụng rootScope làm EventBus không hiệu quả vì $rootScope.$emit()chỉ có bong bóng hướng lên. Tuy nhiên, vì không có phạm vi trên nên $rootScopekhông có gì phải sợ. Vì vậy, nếu bạn chỉ đang sử dụng $rootScope.$emit()$rootScope.$on()bạn sẽ có một EventBus toàn hệ thống nhanh.
Christoph

1
Điều duy nhất bạn cần lưu ý là nếu bạn sử dụng $rootScope.$on()bên trong bộ điều khiển của mình, bạn sẽ cần xóa sạch ràng buộc sự kiện vì nếu không chúng sẽ tổng hợp khi nó tạo một cái mới mỗi khi bộ điều khiển được khởi tạo và chúng không được tự động phá hủy cho bạn vì bạn đang ràng buộc $rootScopetrực tiếp.
Christoph

Phiên bản mới nhất của Angular (1.2.16), và có lẽ trước đó, đã khắc phục vấn đề này. Bây giờ $ Broadcast sẽ không truy cập vào mọi bộ điều khiển hậu duệ mà không có lý do. Nó sẽ chỉ đến thăm những người thực sự lắng nghe sự kiện này. Tôi đã cập nhật jsperf được tham chiếu ở trên để chứng minh rằng sự cố hiện đã được khắc phục: jsperf.com/rootscope-emit-vs-rootscope-broadcast/27
zumalifeguard

14

Sử dụng các phương thức get và set trong một dịch vụ, bạn có thể chuyển tin nhắn giữa các bộ điều khiển rất dễ dàng.

var myApp = angular.module("myApp",[]);

myApp.factory('myFactoryService',function(){


    var data="";

    return{
        setData:function(str){
            data = str;
        },

        getData:function(){
            return data;
        }
    }


})


myApp.controller('FirstController',function($scope,myFactoryService){
    myFactoryService.setData("Im am set in first controller");
});



myApp.controller('SecondController',function($scope,myFactoryService){
    $scope.rslt = myFactoryService.getData();
});

trong HTML HTML bạn có thể kiểm tra như thế này

<div ng-controller='FirstController'>  
</div>

<div ng-controller='SecondController'>
    {{rslt}}
</div>

+1 Một trong những phương pháp rõ ràng một lần bạn đã nói - thật tuyệt vời! Tôi đã triển khai một phiên bản tổng quát hơn với các phương thức set (key, value) và get (key) - một thay thế hữu ích cho $ Broadcast.
TonyWilk

8

Về mã gốc - có vẻ như bạn muốn chia sẻ dữ liệu giữa các phạm vi. Để chia sẻ Dữ liệu hoặc Trạng thái giữa phạm vi $, các tài liệu đề xuất sử dụng dịch vụ:

  • Để chạy mã không trạng thái hoặc trạng thái được chia sẻ trên các bộ điều khiển - Thay vào đó, hãy sử dụng các dịch vụ góc.
  • Để khởi tạo hoặc quản lý vòng đời của các thành phần khác (ví dụ: để tạo các phiên bản dịch vụ).

Tham khảo: Liên kết tài liệu góc ở đây


5

Tôi thực sự đã bắt đầu sử dụng Postal.js như một bus tin nhắn giữa các bộ điều khiển.

Có rất nhiều lợi ích cho nó như một bus tin nhắn như các ràng buộc kiểu AMQP, cách bưu chính có thể tích hợp w / iFrames và ổ cắm web, và nhiều thứ khác.

Tôi đã sử dụng một công cụ trang trí để thiết lập Bưu điện trên $scope.$bus...

angular.module('MyApp')  
.config(function ($provide) {
    $provide.decorator('$rootScope', ['$delegate', function ($delegate) {
        Object.defineProperty($delegate.constructor.prototype, '$bus', {
            get: function() {
                var self = this;

                return {
                    subscribe: function() {
                        var sub = postal.subscribe.apply(postal, arguments);

                        self.$on('$destroy',
                        function() {
                            sub.unsubscribe();
                        });
                    },
                    channel: postal.channel,
                    publish: postal.publish
                };
            },
            enumerable: false
        });

        return $delegate;
    }]);
});

Đây là một liên kết đến một bài đăng trên blog về chủ đề ...
http://jonathancreamer.com/an-angular-event-bus-with-postal-js/


3

Đây là cách tôi thực hiện với Factory / Servicestiêm phụ thuộc đơn giản (DI) .

myApp = angular.module('myApp', [])

# PeopleService holds the "data".
angular.module('myApp').factory 'PeopleService', ()->
  [
    {name: "Jack"}
  ]

# Controller where PeopleService is injected
angular.module('myApp').controller 'PersonFormCtrl', ['$scope','PeopleService', ($scope, PeopleService)->
  $scope.people = PeopleService
  $scope.person = {} 

  $scope.add = (person)->
    # Simply push some data to service
    PeopleService.push angular.copy(person)
]

# ... and again consume it in another controller somewhere...
angular.module('myApp').controller 'PeopleListCtrl', ['$scope','PeopleService', ($scope, PeopleService)->
  $scope.people = PeopleService
]

1
Hai bộ điều khiển của bạn không liên lạc, họ chỉ sử dụng một dịch vụ giống nhau. Đó không phải là điều tương tự.
Greg

@Greg bạn có thể đạt được điều tương tự với ít mã hơn bằng cách có dịch vụ chia sẻ và thêm đồng hồ $ khi cần.
Capaj

3

Tôi thích cách $rootscope.emitđã được sử dụng để đạt được sự giao tiếp. Tôi đề nghị giải pháp hiệu quả và sạch sẽ mà không gây ô nhiễm không gian toàn cầu.

module.factory("eventBus",function (){
    var obj = {};
    obj.handlers = {};
    obj.registerEvent = function (eventName,handler){
        if(typeof this.handlers[eventName] == 'undefined'){
        this.handlers[eventName] = [];  
    }       
    this.handlers[eventName].push(handler);
    }
    obj.fireEvent = function (eventName,objData){
       if(this.handlers[eventName]){
           for(var i=0;i<this.handlers[eventName].length;i++){
                this.handlers[eventName][i](objData);
           }

       }
    }
    return obj;
})

//Usage:

//In controller 1 write:
eventBus.registerEvent('fakeEvent',handler)
function handler(data){
      alert(data);
}

//In controller 2 write:
eventBus.fireEvent('fakeEvent','fakeData');

Đối với rò rỉ bộ nhớ, bạn nên thêm một phương thức bổ sung để hủy đăng ký khỏi trình lắng nghe sự kiện. Dù sao mẫu tốt tầm thường
Raffaeu

2

Đây là cách nhanh chóng và bẩn thỉu.

// Add $injector as a parameter for your controller

function myAngularController($scope,$injector){

    $scope.sendorders = function(){

       // now you can use $injector to get the 
       // handle of $rootScope and broadcast to all

       $injector.get('$rootScope').$broadcast('sinkallships');

    };

}

Đây là một chức năng ví dụ để thêm vào trong bất kỳ bộ điều khiển anh chị em nào:

$scope.$on('sinkallships', function() {

    alert('Sink that ship!');                       

});

và tất nhiên đây là HTML của bạn:

<button ngclick="sendorders()">Sink Enemy Ships</button>

16
Tại sao bạn không tiêm $rootScope?
Pieter Herroelen

1

Bắt đầu góc 1,5 và đó là trọng tâm phát triển dựa trên thành phần. Cách được đề xuất cho các thành phần tương tác là thông qua việc sử dụng thuộc tính 'yêu cầu' và thông qua các ràng buộc thuộc tính (đầu vào / đầu ra).

Một thành phần sẽ yêu cầu một thành phần khác (ví dụ thành phần gốc) và có được một tham chiếu đến bộ điều khiển của nó:

angular.module('app').component('book', {
    bindings: {},
    require: {api: '^app'},
    template: 'Product page of the book: ES6 - The Essentials',
    controller: controller
});

Sau đó, bạn có thể sử dụng các phương thức của thành phần gốc trong thành phần con của bạn:

$ctrl.api.addWatchedBook('ES6 - The Essentials');

Đây là chức năng điều khiển thành phần gốc:

function addWatchedBook(bookName){

  booksWatched.push(bookName);

}

Dưới đây là một tổng quan kiến ​​trúc đầy đủ: Truyền thông thành phần


0

Bạn có thể truy cập chức năng hello này ở bất cứ đâu trong mô-đun

Bộ điều khiển một

 $scope.save = function() {
    $scope.hello();
  }

bộ điều khiển thứ hai

  $rootScope.hello = function() {
    console.log('hello');
  }

Thêm thông tin ở đây


7
Đến bữa tiệc muộn một chút nhưng: đừng làm điều này. Đặt một chức năng trên phạm vi gốc giống như làm cho một chức năng toàn cầu, có thể gây ra tất cả các loại vấn đề.
Dan Pantry

0

Tôi sẽ tạo một dịch vụ và sử dụng thông báo.

  1. Tạo một phương thức trong Dịch vụ thông báo
  2. Tạo một phương thức chung để phát thông báo trong Dịch vụ thông báo.
  3. Từ bộ điều khiển nguồn gọi thông báoService.Method. Tôi cũng vượt qua đối tượng tương ứng để tiếp tục nếu cần.
  4. Trong phương thức, tôi lưu dữ liệu trong dịch vụ thông báo và gọi phương thức thông báo chung.
  5. Trong bộ điều khiển đích tôi lắng nghe ($ scope.on) cho sự kiện phát sóng và truy cập dữ liệu từ Dịch vụ thông báo.

Vì tại bất kỳ thời điểm nào, Dịch vụ thông báo là đơn lẻ, nó sẽ có thể cung cấp dữ liệu bền vững.

Hi vọng điêu nay co ich


0

Bạn có thể sử dụng dịch vụ tích hợp AngularJS $rootScopevà tiêm dịch vụ này vào cả hai bộ điều khiển của bạn. Sau đó, bạn có thể lắng nghe các sự kiện được bắn trên đối tượng $ rootScope.

$ rootScope cung cấp hai bộ điều phối sự kiện được gọi $emit and $broadcastlà chịu trách nhiệm gửi các sự kiện (có thể là các sự kiện tùy chỉnh) và sử dụng $rootScope.$onchức năng để thêm trình lắng nghe sự kiện.


0

Bạn nên sử dụng Dịch vụ, vì $rootscopelà quyền truy cập từ toàn bộ Ứng dụng và nó sẽ tăng tải hoặc bạn sử dụng rootparams nếu dữ liệu của bạn không nhiều hơn.


0
function mySrvc() {
  var callback = function() {

  }
  return {
    onSaveClick: function(fn) {
      callback = fn;
    },
    fireSaveClick: function(data) {
      callback(data);
    }
  }
}

function controllerA($scope, mySrvc) {
  mySrvc.onSaveClick(function(data) {
    console.log(data)
  })
}

function controllerB($scope, mySrvc) {
  mySrvc.fireSaveClick(data);
}

0

Bạn có thể làm điều đó bằng cách sử dụng các sự kiện góc là $ emit và $ Broadcast. Theo kiến ​​thức của chúng tôi, đây là cách tốt nhất, hiệu quả và hiệu quả.

Đầu tiên chúng ta gọi một hàm từ một bộ điều khiển.

var myApp = angular.module('sample', []);
myApp.controller('firstCtrl', function($scope) {
    $scope.sum = function() {
        $scope.$emit('sumTwoNumber', [1, 2]);
    };
});
myApp.controller('secondCtrl', function($scope) {
    $scope.$on('sumTwoNumber', function(e, data) {
        var sum = 0;
        for (var a = 0; a < data.length; a++) {
            sum = sum + data[a];
        }
        console.log('event working', sum);

    });
});

Bạn cũng có thể sử dụng $ rootScope thay cho $ scope. Sử dụng bộ điều khiển của bạn cho phù hợp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.