如何触发在指令内部定义的作用域函数
如何触发在指令内部定义的作用域函数
我在我的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
\n总之:我需要从控制器中触发ng-click=\"addWidgetInternal($event, widget);\"
,而不是从html视图模板文件中触发。
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对象及其所有选项。请查看我帖子的更新部分。