简体   繁体   中英

$broadcast timing issue in angularJS, how to ensure directive is created before broadcasting

I'm having a problem with $broadcast in angularJS. My controller is dynamically adding directive elements to the DOM on page load using the $compile function.

$('#container').prepend($compile('<myDirective></myDirective>')($scope));
$scope.$broadcast('loadIt', stuffIneedLoaded);

What I want to do is to call a directive scope function upon the directive being created and so I used $broadcast. What is happening now is that the $broadcast is called before the directive is done rendering and so the scope.$on in the directive never hears the broadcast.

From the directive link function:

link: function (scope, element, attrs) {
        scope.$on('loadIt') = function (stuffToLoad) {
        //stuff to load
    }
}

The reason I need to use broadcast is because I need to send the directive data from the controller.

http://jsfiddle.net/5ReCu/

The fiddle doesn't work, just boilerplate to help convey what I'm shooting for:

Any ideas? Thank you all in advance!

I would use two directives and call one from another. Further, after compile would call scope method that invokes broadcast. Something like:

var fessmodule = angular.module('myModule', []);

fessmodule.controller('fessCntrl', function ($scope) {
    $scope.recall = function() {
        $scope.$broadcast('loadIt'); 
    }; 
});

fessmodule.$inject = ['$scope'];


fessmodule.directive("myDirective", function() {
    return {
        restrict: 'E',
        template: "<div>test code</div>",        
        link: function (scope, element, attrs) {
            scope.$on("loadIt", function() {
                 console.log('in myDirective on'); 
             });          

        }
    }
});

fessmodule.directive('directiveFoo', function($compile) {
    return {       
        controller: function() {
            console.log('in foo ctrl');            
        },
       link: function (scope, element, attrs) {
        var elem_0 = angular.element(element[0]);
        var a_input = angular.element($compile('<my-directive></my-directive>')(scope));
        elem_0.prepend(a_input);

           scope.recall();
        }
    }
});

Demo Fiddle

as a side note:

I strongly recommend to avoid any DOM update/manipulations in controller. Use directives. By this way we can control and track down most issues with call queue.

This is old, but today I solved something similar this way:

module.controller('moduleCtrl', function ($scope, $interval) {
    $scope.triggerEvent = function() {
        var promise =
            $interval(function () {
                if (scope.$$listenerCount["loadIt"] == null
                    || scope.$$listenerCount["loadIt"] === 0)
                    return;

                scope.$broadcast("loadIt");
                $interval.cancel(promise);
            }, 200);
    }; 
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM