如何触发指令中定义的范围函数 [英] How to trigger a scope function defined inside a Directive
问题描述
我在我里面有很多指令的角应用程序中使用仪表板框架。
I'm using a Dashboard framework in my Angular application which has lots of directives.
在主要的指令有哪些都可以从一个HTML模板使用NG单击名为范围的一些功能,例如,当用户通过一个下拉菜单中增加了一个小工具,仪表盘:
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>
不过,我希望能够调用 addWidgetInternal()
从我的主控制器code。
However, I'd like to be able to call addWidgetInternal()
from my main controller code.
例如,在处理drop事件,我想通过调用 addWidgetInternal
来添加新部件:
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();
}
}
})();
不过,打电话时,我得到一个错误 $ scope.addWidgetInternal()
上面:
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);
}
}
});
和这里的地方我都放在投掷的和仪表指示中的dashboard.html观点:
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>
我使用的可拖动指令放在里面的&LT; IMG&GT;
如下(因此,在上面的控制器code提到的放置事件):
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>
底线:不是触发 NG-点击=addWidgetInternal($事件,部件);
从HTML视图模板文件,我需要从一个触发它控制器。
Bottom line: instead of triggering ng-click="addWidgetInternal($event, widget);"
from an html view template file, I need to trigger it from a controller.
**** ****更新
我结束了移植一些拖放指令逻辑到仪表板上指令code。这样我可以处理的同一范围内的仪表板窗口小部件定义中的DROP事件。
下面是在仪表板更新的链接code
指令:
**** 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);
};
}
问候,
鲍勃
推荐答案
这通常不是为了实现这个强烈推荐的方式,但我发现边缘情况下,整合code那就是当这可能是特别handy-的角度之外。
This generally is not a highly recommended way to accomplish this, but I have found edge cases where this can be handy- especially when integrating code that is outside of Angular.
我制作的code提供一个工作演示,你可以随意从那里建立在一个轻型版本的小提琴。基本上,我抓住按id你的元素和'挖'到它的范围,然后调用函数的范围。在我的例子,我打电话给你的 chart_area
像
I crafted a light version fiddle of your code to provide a working demo which you can feel free to build on from there. Basically, I am grabbing your element by id and 'digging' into it's scope, then calling the scope function. In my example, I call your chart_area
like
angular
.element(document.getElementById('dash')).scope().addWidgetInternal();
.scope()
.addWidgetInternal(message);
的消息
在这种情况下只是一个字符串,我从UI发送和 addWidgetInternal注销()
在指令中,从控制器调用
message
in this case is just a string I am sending from the UI and logging out in addWidgetInternal()
in the directive, called from the controller
这篇关于如何触发指令中定义的范围函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!