如何触发在指令内部定义的作用域函数

8 浏览
0 Comments

如何触发在指令内部定义的作用域函数

我在我的Angular应用程序中使用了一个仪表板框架,其中包含许多指令。\n在主指令中,有一些作用域函数,可以通过ng-click从html模板中调用,例如,当用户通过下拉菜单向仪表板添加小部件时:\n


\n然而,我希望能够从我的主控制器代码中调用addWidgetInternal()。\n例如,在处理拖放事件时,我希望通过调用addWidgetInternal来添加新的小部件:\n

(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',
    };
    // 拖放事件         
    $scope.handleDrop = function () {
        // $scope.addWidgetInternal(); // *** 无法直接调用其他指令的此函数!
        // **** 更新:一种解决方案,访问“dashboard”指令中的作用域函数
        angular.element(document.getElementById('dash')).scope().addWidgetInternal();
    }
}
})();

\n但是当以上调用$scope.addWidgetInternal()时,我会收到一个错误:\n

      TypeError: undefined is not a function

\n以下是主要仪表板指令的一部分代码 - 具体来说是link函数:\n

 link: function (scope) {
          scope.widgetDefs = new WidgetDefCollection(scope.options.widgetDefinitions);
          scope.addWidgetInternal = function (event, widgetDef) {
              event.preventDefault();
              scope.addWidget(widgetDef);
          };
  }

\n下面是可拖放指令的代码:\n

.directive('droppable', function () {
  return {
    restrict: 'A',
    scope: {
        drop: '&',
    },
    require: '?dashboard',  // 可选地请求'dashboard'指令;参见下面的'drop'
    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));
            // 调用从dashboard.html中的'drop'属性传入的drop函数
            scope.$apply(function (scope) {
                var fn = scope.drop();
                if ('undefined' !== typeof fn) {                        
                    fn(e);   // 将事件传递给调用函数
                }                    
            });
            return false;
        }, false);
    }
}
});

\n下面是dashboard.html视图,在其中放置了droppable和dashboard指令:\n

    

\n我使用的可拖动指令放置在中,如下所示(因此,上面的控制器代码中提到的拖放事件):\n

   
        
            Hierarchy Grid
           
        Area Chart            
    

\n总之:我需要从控制器中触发ng-click=\"addWidgetInternal($event, widget);\",而不是从html视图模板文件中触发。

0
0 Comments

AngularJS中有一种不太推荐的方法可以触发指令内部定义的作用域函数。这种方法在集成Angular之外的代码时可能会有一些特殊情况。下面的代码提供了一个工作示例,可以在此基础上进行修改。基本上,我通过元素的id来获取它的作用域,并调用作用域函数。在我的示例中,我这样调用了chart_area

angular
    .element(document.getElementById('dash')).scope().addWidgetInternal();
    .scope()
    .addWidgetInternal(message);

在这种情况下,message只是一个我从UI发送并在指令中的addWidgetInternal()中记录的字符串,由控制器调用。

此方法对你有用吗?我还尝试回答了你的另一个问题。查看答案stackoverflow.com/a/27864420/1464112。祝你好运。

sal - 我从来没有想到你提供的这个解决方法。它确实直接调用了我的dashboard指令中的addWidgetInternal()。我更新了elementById,改为获取'dash',也就是我放置的地方。

现在我只需要弄清楚如何传递原始的两个参数ng-click="addWidgetInternal($event, widget)"。我需要在droppable指令的'drop'监听器中获取事件和widget类型。

没问题,只需从UI中传递$event,并更新所有的函数签名,直到指令为止。这是一个使用相同示例的fiddle,演示了如何做到这一点。请考虑接受答案,如果它们对你有用的话。jsfiddle.net/aregnfy1

我最后创建了一个在'dashboard'指令的链接部分中的e.ondrop事件。这样我就可以访问widgetDefs对象及其所有选项。请查看我帖子的更新部分。

0