scope.$on is not working when created inside a directive
Asked Answered
R

2

10

I have created a directive for my application which is mentioned in the following question How do you serve a file for download with AngularJS or Javascript? Directive code is as like below

    appModule.directive('fileDownload', function ($compile) {
        var fd = {
            restrict: 'A',
            link: function (scope, iElement, iAttrs) {

                scope.$on("downloadFile", function (e, url) {
                    var iFrame = iElement.find("iframe");
                    if (!(iFrame && iFrame.length > 0)) {
                        iFrame = $("<iframe style='position:fixed;display:none;top:-1px;left:-1px;'/>");
                        iElement.append(iFrame);
                    }
                    iFrame.attr("src", url);
                });
            }
        };
        return fd;
    });

Here scope.$on is used, when I call this event via $scope.$emit or $scope.$broadcast, it is not working. My controller code is like below

    function reportsController($scope, $http) {
        var self = this;

        $scope.$broadcast("downloadFile", 'http://google.com');
        $scope.$emit("downloadFile", 'http://google.com');
    }

and my html file is as below

    <div ng-controller="reportsController" id="repctrl">
        <a file-download></a>
    </div>

What I am doing wrong here?

@Edit: Added the subscribe ($on) in the compile phase so as to avoid the usage of $timeout in controller. Here you can look the example

Reverence answered 17/12, 2013 at 7:15 Comment(0)
H
7

I think your controller is being initialized before your directive.. so the $on starts listening after the $emit, $broadcast already happened.

see this plunker

open the console and you can see when the console.logs happen:

controller init happened script.js:16
link happened script.js:7
$scope.test() happened script.js:21
scope.$on happened script.js:9
scope.$on happened 

If you initialize the controller with ng-view or do the emit/broadcast after the directive is created, it should work.

Housecarl answered 17/12, 2013 at 7:52 Comment(2)
why are you doing a .controller on your returned fd object?Defiance
fd is the return value of the 2nd argument of the directive function, which is just returning the directive config. The .controller is actually being called on the return value of .directive, which is a reference to the module that called it.Housecarl
L
1

something similar happen to me when i try to call a function in the directive of a modal,

what i had to do was to make a delay after I made the call to show the modal:

        $timeout(function () {
            $rootScope.$broadcast('obtiene-plantillas');
        }, 500);
Lockman answered 7/6, 2017 at 14:40 Comment(1)
Here we don't need to give the time as second argument for $timeout. I have edited my question and added my latest finding as solution in the fiddleReverence

© 2022 - 2024 — McMap. All rights reserved.