What is the best way to call a method in a controller from a service in angular?
<p>I've done some research on this question both in SO and on Google as well. But none of the answers serve my purpose.</p>

<p>I have a modal in an HTML view, which I use to show popup notifications in my app.
I want to show some buttons ('OK', 'Cancel', 'Login', etc.,) in a <code>div</code> on modal which I pass dynamically as a JS object. Name of the button being the key and the callback function being the value.</p>

<p><strong>Examples:</strong></p>

<pre><code>{
    "Login": function(){....}
}

{
    "OK": function(){...},
    "Cancel": function(){...}
}
</code></pre>

<p>Now I pass this kind of objects to a method <code>showPopup(message, buttonMap)</code> in the controller of the popup modal I have in view.</p>

<p><code>message</code> being the display message on the popup and <code>buttonMap</code> being the object in examples.</p>

<p><strong>Controller:</strong></p>

<pre><code>angular.module('core').controller('PopupController', ['$rootScope', 'LogService', 'MessageHandlerService',
    function ($rootScope, LogService, MessageHandlerService) {    
        var ctrl = this;

        ctrl.buttonMap = {};
        ctrl.btnWidth = 100;

        $rootScope.$on('popup', showPopup);

        function showPopup (event, message, buttonMap) {
            $('#genericModalDialog .popup-content p').html(message);
            ctrl.buttonMap = buttonMap;
            var numberOfButtons = Object.keys(buttonMap).length;
            ctrl.btnWidth = (100 - numberOfButtons*2)/numberOfButtons;
            $("#genericModalDialog").modal('show');
        }

        ctrl.callbackFor = function callbackFor(key) {
            ctrl.buttonMap[key].call(null);
        };
    }
]);
</code></pre>

<p><strong>Service:</strong></p>

<pre><code>    angular.module('core').service('PopupService', ['$rootScope', 'LogService', 'CacheService', 'MessageHandlerService',
        function ($rootScope, LogService) {

            this.isPopupShown = function (){
                return $("#genericModalDialog").hasClass('in');
            }

            this.showPopup = function (message, btnMap){
                $rootScope.$broadcast('popup', message, btnMap);
            }

            this.closePopup = function (){
                $("#genericModalDialog").modal('hide');
            }

        }
    ]);
</code></pre>

<p><strong>View:</strong></p>

<pre><code>&lt;div ng-controller="PopupController as popupCtrl" class="modal fade" id="genericModalDialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"&gt;
  &lt;div class="vertical-alignment-helper"&gt;
    &lt;div class="modal-dialog vertical-align-center" style="width:94%;"&gt;
      &lt;div class="modal-content"&gt;
        &lt;div class="modal-body"&gt;
          &lt;br/&gt;&lt;br/&gt;
          &lt;div class="popup-content"&gt;
            &lt;p align="center"&gt;&lt;/p&gt;&lt;br/&gt;
            &lt;div class="popup-action"&gt;
              &lt;button type="button" class="btn" style="width:{{popupCtrl.btnWidth}}%; margin:1%" ng-repeat="(buttonName, callBack) in popupCtrl.buttonMap" ng-click="popupCtrl.callbackFor(buttonName)"&gt;{{buttonName}}&lt;/button&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</code></pre>

<p>Since I don't want to instantiate <code>PopupController</code> in every other controller/service, I've written a service called <code>PopupService</code> which has a method that can called and will <code>$broadcast</code> an event called <code>"popup"</code> on <code>$rootscope</code> and I am handling this event in <code>PopupController</code>. Everything is triggered and working properly in this case. The only problem I face is the delay in rendering the popup on the UI, I see the message as soon as the popup is displayed but the rendering of buttons is very slow (approx 3 secs) this is because of loading of some other web page in the background.</p>

<p>When I searched about the issue on the internet I also found this total setup can be changed to a directive and the rendering of dynamic content (in this case the popup and buttons on it.) could be placed in a link function of the directive.</p>

<p>Another approach I saw was directly handling the DOM manipulation in the service which of course is not a good way.</p>

<p>Did I miss any other approach or a solution to this issue?</p>

<p>All I want to know is what would the best way be, to handling this situation which is programmatically and design wise good.</p>

<p>If I am not clear please let me know. I'll try explaining the problem again.</p>