I'm using a Dashboard framework in my Angular application which has lots of directives.
Within the main directive there are some scope functions which are getting called from an html template using ng-click, for example, when a user adds a widget to the dashboard via a dropdown menu :
   <div class="btn-group" ng-if="options.widgetButtons">
        <button ng-repeat="widget in widgetDefs"
                ng-click="addWidgetInternal($event, widget);" type="button" class="btn btn-primary">
            {{widget.name}}
        </button>
    </div>
However, I'd like to be able to call addWidgetInternal() from my main controller code.
For example, upon handling a drop event I'd like to add the new widget by calling addWidgetInternal:
(function () {
'use strict';
angular.module('rage')
    .controller('MainCtrl',
        ['$scope', '$interval', '$window', 'widgetDefinitions',
        'defaultWidgets', 'gadgetInitService', initOptions]);
function initOptions($scope, $interval, $window, widgetDefinitions, defaultWidgets, gadgetInitService) {
    this.userName = 'Bob';
    this.userRole = 'Risk Analyst';
    this.descriptionText = 'Risk Engine';
    $scope.dashboardOptions = {
        widgetDefinitions: widgetDefinitions,   
        defaultWidgets: defaultWidgets,
        storage: $window.localStorage,
        storageId: 'rage.ui',
    };
    // DRAG AND DROP EVENTS         
    $scope.handleDrop = function () {
        // $scope.addWidgetInternal(); // *** CANNOT MAKE THIS CALL DIRECTLY TO OTHER DIRECTIVE !
        // **** UPDATE: a work-around to access scope function in 'dashboard' directive
        angular.element(document.getElementById('dash')).scope().addWidgetInternal();
    }
}
})();
But I get an error when calling $scope.addWidgetInternal() above:
      TypeError: undefined is not a function
and here's a snippet from the main dashboard directive - specifically, the link function:
 link: function (scope) {
          scope.widgetDefs = new WidgetDefCollection(scope.options.widgetDefinitions);
          scope.addWidgetInternal = function (event, widgetDef) {
              event.preventDefault();
              scope.addWidget(widgetDef);
          };
  }
the droppable directive is the following:
.directive('droppable', function () {
  return {
    restrict: 'A',
    scope: {
        drop: '&',
    },
    require: '?dashboard',  // 'dashboard' directive is optionally requested; see 'drop' below
    link: function (scope, element, attributes, dashboardCtrl) {
        var el = element[0];
        el.addEventListener('drop', function (e) {
            if (e.preventDefault) { e.preventDefault(); }
            this.classList.remove('over');
            var item = document.getElementById(e.dataTransfer.getData('Text'));                
            this.appendChild(item.cloneNode(true));
            // call the drop function passed in from the dashboard.html 'drop' attribute
            scope.$apply(function (scope) {
                var fn = scope.drop();
                if ('undefined' !== typeof fn) {                        
                    fn(e);   // PASS THE EVENT TO CALLING FUNCTION
                }                    
            });
            return false;
        }, false);
    }
}
});
and here's the dashboard.html view where I place both droppable and dashboard directives:
    <div class="col-lg-12" data-droppable drop="handleDrop">
        <div id="dash" dashboard="dashboardOptions" class="dashboard-container"></div>
    </div>
The draggable directive I'm using is placed inside an <img> as follows (hence, the drop event mentioned in the above controller code) :
   <tr>
        <td >
            <img data-draggable id="chart_gridhier" src="images/chart_gridhier.jpg" title="TreeGrid" alt="Hierarchy Grid" width="80" height="95">
        </td>   
        <td><img data-draggable "id="chart_area" src="images/chart_area.jpg"  title="Area Chart" alt="Area Chart" width="80" height="95"></td>            
    </tr>
Bottom line: instead of triggering ng-click="addWidgetInternal($event, widget);" from an html view template file, I need to trigger it from a controller.
**** UPDATE ****
I ended up porting some of the drag-drop directive logic INTO the dashboard directive code. This way I can handle the DROP event within the same scope as the dashboard widget definitions. 
Here's the updated link code in the dashboard directive :
link: function (scope, element) {
          // handle drop event from the gadgets drag-drop operation (see gadgets-include.html)
          var el = element[0];
          el.ondrop = function (e) {
              e.dataTransfer.dropEffect = 'move';
              var item = document.getElementById(e.dataTransfer.getData('text'));                 
              this.appendChild(item.cloneNode(true));                  
              var newWidget = _.findWhere(scope.widgetDefs, { name: item.id });
              // This will add the new widget div to the dashboard
              scope.addWidgetInternal(e, newWidget);
          };
  }
regards,
Bob
 
    